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

📄 mptscsih.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	pScsiReq->LUN[1] = lun;	pScsiReq->LUN[2] = 0;	pScsiReq->LUN[3] = 0;	pScsiReq->LUN[4] = 0;	pScsiReq->LUN[5] = 0;	pScsiReq->LUN[6] = 0;	pScsiReq->LUN[7] = 0;	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(hd->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(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)			goto fail;	}	hd->ScsiLookup[my_idx] = SCpnt;	SCpnt->host_scribble = NULL;#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION	if (hd->ioc->bus_type == SCSI) {		int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];		int issueCmd = 1;		if (dvStatus || hd->ioc->spi_data.forceDv) {			if ((dvStatus & MPT_SCSICFG_NEED_DV) ||				(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {				unsigned long lflags;				/* Schedule DV if necessary */				spin_lock_irqsave(&dvtaskQ_lock, lflags);				if (!dvtaskQ_active) {					dvtaskQ_active = 1;					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);					INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);					schedule_work(&dvTaskQ_task);				} else {					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);				}				hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;			}			/* Trying to do DV to this target, extend timeout.			 * Wait to issue until flag is clear			 */			if (dvStatus & MPT_SCSICFG_DV_PENDING) {				mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);				issueCmd = 0;			}			/* Set the DV flags.			 */			if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)				mptscsih_set_dvflags(hd, pScsiReq);			if (!issueCmd)				goto fail;		}	}#endif	mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);	dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",			hd->ioc->name, SCpnt, mf, my_idx));	DBG_DUMP_REQUEST_FRAME(mf)	return 0; fail:	hd->ScsiLookup[my_idx] = NULL;	mptscsih_freeChainBuffers(hd->ioc, my_idx);	mpt_free_msg_frame(hd->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((MYIOC_s_INFO_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. *	Fall through to mpt_HardResetHandler if: not operational, too many *	failed TM requests or handshake failure. * *	@ioc: Pointer to MPT_ADAPTER structure *	@type: Task Management type *	@target: Logical Target ID for reset (if appropriate) *	@lun: Logical Unit for reset (if appropriate) *	@ctx2abort: Context for the task to be aborted (if appropriate) * *	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 -1 if FAILED. */static intmptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout){	MPT_ADAPTER	*ioc;	int		 rc = -1;	int		 doTask = 1;	u32		 ioc_raw_state;	unsigned long	 flags;	/* If FW is being reloaded currently, return success to	 * the calling function.	 */	if (hd == NULL)		return 0;	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));	// 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((KERN_INFO MYNAM ": %s: TMHandler abort: "			   "Timed out waiting for last TM (%d) to complete! \n",			   hd->ioc->name, hd->tmPending));			return FAILED;		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "			   "Timed out waiting for last TM (%d) to complete! \n",			   hd->ioc->name, hd->tmPending));			return FAILED;		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "			   "Timed out waiting for last TM (%d) to complete! \n",			   hd->ioc->name, hd->tmPending));			if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))				return FAILED;			doTask = 0;		}	} else {		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);		hd->tmPending |=  (1 << type);		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);	}	/* Is operational?	 */	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);#ifdef MPT_DEBUG_RESET	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {		printk(MYIOC_s_WARN_FMT			"TM Handler: IOC Not operational(0x%x)!\n",			hd->ioc->name, ioc_raw_state);	}#endif	if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)				&& !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {		/* Isse the Task Mgmt request.		 */		if (hd->hard_resets < -1)			hd->hard_resets++;		rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, 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	 */	if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||		ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",			 hd->ioc->name));		rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);	}	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));	return rc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_IssueTaskMgmt - Generic send Task Management function. *	@hd: Pointer to MPT_SCSI_HOST structure *	@type: Task Management type *	@target: Logical Target ID for reset (if appropriate) *	@lun: Logical Unit for reset (if appropriate) *	@ctx2abort: Context for the task to be aborted (if appropriate) * *	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, -999 for "no msg frames", *	else other non-zero value returned. */static intmptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout){	MPT_FRAME_HDR	*mf;	SCSITaskMgmt_t	*pScsiTm;	int		 ii;	int		 retval;	/* Return Fail to calling function if no message frames available.	 */	if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {		dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",				hd->ioc->name));		return FAILED;	}	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",			hd->ioc->name, mf));	/* Format the Request	 */	pScsiTm = (SCSITaskMgmt_t *) mf;	pScsiTm->TargetID = target;	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;	for (ii= 0; ii < 8; ii++) {		pScsiTm->LUN[ii] = 0;	}	pScsiTm->LUN[1] = lun;	for (ii=0; ii < 7; ii++)		pScsiTm->Reserved2[ii] = 0;	pScsiTm->TaskMsgContext = ctx2abort;	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",			hd->ioc->name, ctx2abort, type));	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,		CAN_SLEEP)) != 0) {		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,			hd->ioc, mf));		mpt_free_msg_frame(hd->ioc, mf);		return retval;	}	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {		dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,			hd->ioc, mf));		mpt_free_msg_frame(hd->ioc, mf);		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",			 hd->ioc->name));		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);	}	return retval;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	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_ADAPTER	*ioc;	MPT_FRAME_HDR	*mf;	u32		 ctx2abort;	int		 scpnt_idx;	int		 retval;	/* If we can't locate our host adapter structure, return FAILED status.	 */	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {		SCpnt->result = DID_RESET << 16;		SCpnt->scsi_done(SCpnt);		dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "			   "Can't locate host! (sc=%p)\n",			   SCpnt));		return FAILED;	}	ioc = hd->ioc;	if (hd->resetPending) {		return FAILED;	}	if (hd->timeouts < -1)		hd->timeouts++;	/* Find this command	 */	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {		/* Cmd not found in ScsiLookup.		 * Do OS callback.		 */		SCpnt->result = DID_RESET << 16;		dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "			   "Command not in the active list! (sc=%p)\n",			   hd->ioc->name, SCpnt));		return SUCCESS;	}	printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",	       hd->ioc->name, SCpnt);	scsi_print_command(SCpnt);	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!	 * (the IO to be ABORT'd)	 *	 * NOTE: Since we do not byteswap MsgContext, we do not	 *	 swap it here either.  It is an opaque cookie to	 *	 the controller, so it does not matter. -DaveM	 */	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;	hd->abortSCpnt = SCpnt;	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,		SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,		ctx2abort, 2 /* 2 second timeout */);	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",		hd->ioc->name,		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);	if (retval == 0)		return SUCCESS;	if(retval != FAILED ) {		hd->tmPending = 0;		hd->tmState = TM_STATE_NONE;	}	return FAILED;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant *	@SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to * *	(linux scsi_host_template.eh_dev_reset_handler routine)

⌨️ 快捷键说明

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