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

📄 mptscsih.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (hd->resetPending) {		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",			ioc->name, SCpnt));		return SCSI_MLQUEUE_HOST_BUSY;	}	/*	 *  Put together a MPT SCSI request...	 */	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {		dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",				ioc->name));		return SCSI_MLQUEUE_HOST_BUSY;	}	pScsiReq = (SCSIIORequest_t *) mf;	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);	ADD_INDEX_LOG(my_idx);	/*    TUR's being issued with scsictl=0x02000000 (DATA_IN)!	 *    Seems we may receive a buffer (datalen>0) even when there	 *    will be no data transfer!  GRRRRR...	 */	if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {		datalen = scsi_bufflen(SCpnt);		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {		datalen = scsi_bufflen(SCpnt);		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */	} else {		datalen = 0;		scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;	}	/* Default to untagged. Once a target structure has been allocated,	 * use the Inquiry data to determine if device supports tagged.	 */	if (vdevice	    && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)	    && (SCpnt->device->tagged_supported)) {		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;	} else {		scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;	}	/* Use the above information to set up the message frame	 */	pScsiReq->TargetID = (u8) vdevice->vtarget->id;	pScsiReq->Bus = vdevice->vtarget->channel;	pScsiReq->ChainOffset = 0;	if (vdevice->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;	else		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;	pScsiReq->CDBLength = SCpnt->cmd_len;	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;	pScsiReq->Reserved = 0;	pScsiReq->MsgFlags = mpt_msg_flags();	int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);	pScsiReq->Control = cpu_to_le32(scsictl);	/*	 *  Write SCSI CDB into the message	 */	cmd_len = SCpnt->cmd_len;	for (ii=0; ii < cmd_len; ii++)		pScsiReq->CDB[ii] = SCpnt->cmnd[ii];	for (ii=cmd_len; ii < 16; ii++)		pScsiReq->CDB[ii] = 0;	/* DataLength */	pScsiReq->DataLength = cpu_to_le32(datalen);	/* SenseBuffer low address */	pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));	/* Now add the SG list	 * Always have a SGE even if null length.	 */	if (datalen == 0) {		/* Add a NULL SGE */		mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,			(dma_addr_t) -1);	} else {		/* Add a 32 or 64 bit SGE */		if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)			goto fail;	}	SCpnt->host_scribble = (unsigned char *)mf;	mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",			ioc->name, SCpnt, mf, my_idx));	DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);	return 0; fail:	mptscsih_freeChainBuffers(ioc, my_idx);	mpt_free_msg_frame(ioc, mf);	return SCSI_MLQUEUE_HOST_BUSY;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_freeChainBuffers - Function to free chain buffers associated *	with a SCSI IO request *	@hd: Pointer to the MPT_SCSI_HOST instance *	@req_idx: Index of the SCSI IO request frame. * *	Called if SG chain buffer allocation fails and mptscsih callbacks. *	No return. */static voidmptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx){	MPT_FRAME_HDR *chain;	unsigned long flags;	int chain_idx;	int next;	/* Get the first chain index and reset	 * tracker state.	 */	chain_idx = ioc->ReqToChain[req_idx];	ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;	while (chain_idx != MPT_HOST_NO_CHAIN) {		/* Save the next chain buffer index */		next = ioc->ChainToChain[chain_idx];		/* Free this chain buffer and reset		 * tracker		 */		ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;		chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer					+ (chain_idx * ioc->req_sz));		spin_lock_irqsave(&ioc->FreeQlock, flags);		list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);		spin_unlock_irqrestore(&ioc->FreeQlock, flags);		dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",				ioc->name, chain_idx));		/* handle next */		chain_idx = next;	}	return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	Reset Handling *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_TMHandler - Generic handler for SCSI Task Management. *	@hd: Pointer to MPT SCSI HOST structure *	@type: Task Management type *	@channel: channel number for task management *	@id: Logical Target ID for reset (if appropriate) *	@lun: Logical Unit for reset (if appropriate) *	@ctx2abort: Context for the task to be aborted (if appropriate) *	@timeout: timeout for task management control * *	Fall through to mpt_HardResetHandler if: not operational, too many *	failed TM requests or handshake failure. * *	Remark: Currently invoked from a non-interrupt thread (_bh). * *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC *	will be active. * *	Returns 0 for SUCCESS, or %FAILED. **/intmptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout){	MPT_ADAPTER	*ioc;	int		 rc = -1;	u32		 ioc_raw_state;	unsigned long	 flags;	ioc = hd->ioc;	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));	// SJR - CHECKME - Can we avoid this here?	// (mpt_HardResetHandler has this check...)	spin_lock_irqsave(&ioc->diagLock, flags);	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {		spin_unlock_irqrestore(&ioc->diagLock, flags);		return FAILED;	}	spin_unlock_irqrestore(&ioc->diagLock, flags);	/*  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.	 *  The call to mptscsih_tm_pending_wait() will set the pending flag	 *  if we are	 *  successful. Otherwise, reload the FW.	 */	if (mptscsih_tm_pending_wait(hd) == FAILED) {		if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "			   "Timed out waiting for last TM (%d) to complete! \n",			   ioc->name, hd->tmPending));			return FAILED;		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "				"reset: Timed out waiting for last TM (%d) "				"to complete! \n", ioc->name,				hd->tmPending));			return FAILED;		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "			   "Timed out waiting for last TM (%d) to complete! \n",			  ioc->name, hd->tmPending));			return FAILED;		}	} else {		spin_lock_irqsave(&ioc->FreeQlock, flags);		hd->tmPending |=  (1 << type);		spin_unlock_irqrestore(&ioc->FreeQlock, flags);	}	ioc_raw_state = mpt_GetIocState(ioc, 0);	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {		printk(MYIOC_s_WARN_FMT			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",			ioc->name, type, ioc_raw_state);		printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);		if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)			printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "			    "FAILED!!\n", ioc->name);		return FAILED;	}	if (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.	 */	if (hd->hard_resets < -1)		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",		       ioc->name);	else		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",			   ioc->name));	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT			"TMHandler rc = %d!\n", ioc->name, rc));	return rc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_IssueTaskMgmt - Generic send Task Management function. *	@hd: Pointer to MPT_SCSI_HOST structure *	@type: Task Management type *	@channel: channel number for task management *	@id: Logical Target ID for reset (if appropriate) *	@lun: Logical Unit for reset (if appropriate) *	@ctx2abort: Context for the task to be aborted (if appropriate) *	@timeout: timeout for task management control * *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer) *	or a non-interrupt thread.  In the former, must not call schedule(). * *	Not all fields are meaningfull for all task types. * *	Returns 0 for SUCCESS, or FAILED. * **/static intmptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout){	MPT_FRAME_HDR	*mf;	SCSITaskMgmt_t	*pScsiTm;	int		 ii;	int		 retval;	MPT_ADAPTER 	*ioc = hd->ioc;	/* Return Fail to calling function if no message frames available.	 */	if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",				ioc->name));		return FAILED;	}	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",			ioc->name, mf));	/* Format the Request	 */	pScsiTm = (SCSITaskMgmt_t *) mf;	pScsiTm->TargetID = id;	pScsiTm->Bus = channel;	pScsiTm->ChainOffset = 0;	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;	pScsiTm->Reserved = 0;	pScsiTm->TaskType = type;	pScsiTm->Reserved1 = 0;	pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;	int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);	for (ii=0; ii < 7; ii++)		pScsiTm->Reserved2[ii] = 0;	pScsiTm->TaskMsgContext = ctx2abort;	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "		"type=%d\n", ioc->name, ctx2abort, type));	DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);	if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&	    (ioc->facts.MsgVersion >= MPI_VERSION_01_05))		mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);	else {		retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,			sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);		if (retval) {			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"			" (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd,			ioc, mf, retval));			goto fail_out;		}	}	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {		dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"			" (hd %p, ioc %p, mf %p) \n", ioc->name, hd,			ioc, mf));		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",			 ioc->name));		retval = mpt_HardResetHandler(ioc, CAN_SLEEP);		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",			 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; fail_out:	/*	 * Free task managment mf, and corresponding tm flags	 */	mpt_free_msg_frame(ioc, mf);	hd->tmPending = 0;	hd->tmState = TM_STATE_NONE;	return FAILED;}static intmptscsih_get_tm_timeout(MPT_ADAPTER *ioc){	switch (ioc->bus_type) {	case FC:		return 40;	case SAS:		return 10;	case SPI:	default:		return 2;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant *	@SCpnt: Pointer to scsi_cmnd structure, IO to be aborted * *	(linux scsi_host_template.eh_abort_handler routine) * *	Returns SUCCESS or FAILED. **/intmptscsih_abort(struct scsi_cmnd * SCpnt){	MPT_SCSI_HOST	*hd;	MPT_FRAME_HDR	*mf;	u32		 ctx2abort;	int		 scpnt_idx;	int		 retval;	VirtDevice	 *vdevice;	ulong	 	 sn = SCpnt->serial_number;	MPT_ADAPTER	*ioc;	/* If we can't locate our host adapter structure, return FAILED status.	 */	if ((hd = shost_priv(SCpnt->device->host)) == NULL) {		SCpnt->result = DID_RESET << 16;		SCpnt->scsi_done(SCpnt);		printk(KERN_ERR MYNAM ": task abort: "		    "can't locate host! (sc=%p)\n", SCpnt);		return FAILED;	}	ioc = hd->ioc;	printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",	       ioc->name, SCpnt);	scsi_print_command(SCpnt);	vdevice = SCpnt->device->hostdata;	if (!vdevice || !vdevice->vtarget) {		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT		    "task abort: device has been deleted (sc=%p)\n",		    ioc->name, SCpnt));		SCpnt->result = DID_NO_CONNECT << 16;		SCpnt->scsi_done(SCpnt);		retval = 0;		goto out;	}	/* Task aborts are not supported for hidden raid components.

⌨️ 快捷键说明

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