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

📄 mptscsih.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (!count)			printk(KERN_ERR MYNAM ": ERROR - TaskMgmt thread still active!\n");	}	spin_unlock_irqrestore(&mytaskQ_lock, flags);#endif#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION	/* Check DV thread active */	count = 10 * HZ;	spin_lock_irqsave(&dvtaskQ_lock, flags);	while(dvtaskQ_active && --count) {		spin_unlock_irqrestore(&dvtaskQ_lock, flags);		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(1);		spin_lock_irqsave(&dvtaskQ_lock, flags);	}	spin_unlock_irqrestore(&dvtaskQ_lock, flags);	if (!count)		printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)	else		printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);#endif#endif	unregister_reboot_notifier(&mptscsih_notifier);	if (hd != NULL) {		int sz1, sz2, sz3, sztarget=0;		int szchain = 0;		int szQ = 0;		int scale;		/* Synchronize disk caches		 */		(void) mptscsih_synchronize_cache(hd, 0);		sz1 = sz2 = sz3 = 0;		if (hd->ioc->req_sz <= 64)			scale = MPT_SG_REQ_64_SCALE;		else if (hd->ioc->req_sz <= 96)			scale = MPT_SG_REQ_96_SCALE;		else			scale = MPT_SG_REQ_128_SCALE;		if (hd->ScsiLookup != NULL) {			sz1 = hd->ioc->req_depth * sizeof(void *);			kfree(hd->ScsiLookup);			hd->ScsiLookup = NULL;		}		if (hd->ReqToChain != NULL) {			szchain += scale * hd->ioc->req_depth * sizeof(int);			kfree(hd->ReqToChain);			hd->ReqToChain = NULL;		}		if (hd->ChainToChain != NULL) {			szchain += scale * hd->ioc->req_depth * sizeof(int);			kfree(hd->ChainToChain);			hd->ChainToChain = NULL;		}		if (hd->ChainBuffer != NULL) {			sz2 = scale * hd->ioc->req_depth * hd->ioc->req_sz;			szchain += sz2;			pci_free_consistent(hd->ioc->pcidev, sz2,				    hd->ChainBuffer, hd->ChainBufferDMA);			hd->ChainBuffer = NULL;		}		if (hd->memQ != NULL) {			szQ = host->can_queue * sizeof(MPT_DONE_Q);			kfree(hd->memQ);			hd->memQ = NULL;		}		if (hd->Targets != NULL) {			int max, ii;			/*			 * Free any target structures that were allocated.			 */			if (hd->is_spi) {				max = MPT_MAX_SCSI_DEVICES;			} else {				max = MPT_MAX_FC_DEVICES;			}			for (ii=0; ii < max; ii++) {				if (hd->Targets[ii]) {					kfree(hd->Targets[ii]);					hd->Targets[ii] = NULL;					sztarget += sizeof(VirtDevice);				}			}			/*			 * Free pointer array.			 */			sz3 = max * sizeof(void *);			kfree(hd->Targets);			hd->Targets = NULL;		}		dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",				hd->ioc->name, sz1, szchain, sz3, sztarget));		dprintk(("Free'd done and free Q (%d) memory\n", szQ));	}	/* NULL the Scsi_Host pointer	 */	hd->ioc->sh = NULL;	scsi_unregister(host);	if (mpt_scsi_hosts) {		if (--mpt_scsi_hosts == 0) {			mpt_reset_deregister(ScsiDoneCtx);			dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));			mpt_event_deregister(ScsiDoneCtx);			dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));			mpt_deregister(ScsiScanDvCtx);			mpt_deregister(ScsiTaskCtx);			mpt_deregister(ScsiDoneCtx);			if (info_kbuf != NULL)				kfree(info_kbuf);		}	}	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_halt - Process the reboot notification *	@nb: Pointer to a struct notifier_block (ignored) *	@event: event (SYS_HALT, SYS_RESTART, SYS_POWER_OFF) *	@buf: Pointer to a data buffer (ignored) * *	This routine called if a system shutdown or reboot is to occur. * *	Return NOTIFY_DONE if this is something other than a reboot message. *		NOTIFY_OK if this is a reboot message. */static intmptscsih_halt(struct notifier_block *nb, ulong event, void *buf){	MPT_ADAPTER *ioc = NULL;	MPT_SCSI_HOST *hd = NULL;	/* Ignore all messages other than reboot message	 */	if ((event != SYS_RESTART) && (event != SYS_HALT)		&& (event != SYS_POWER_OFF))		return (NOTIFY_DONE);	for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc =	mpt_adapter_find_next(ioc)) {		/* Flush the cache of this adapter		 */		if (ioc->sh) {			hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;			if (hd) {				mptscsih_synchronize_cache(hd, 0);			}		}	}	unregister_reboot_notifier(&mptscsih_notifier);	return NOTIFY_OK;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_info - Return information about MPT adapter *	@SChost: Pointer to Scsi_Host structure * *	(linux Scsi_Host_Template.info routine) * *	Returns pointer to buffer where information was written. */const char *mptscsih_info(struct Scsi_Host *SChost){	MPT_SCSI_HOST *h;	int size = 0;	if (info_kbuf == NULL)		if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)			return info_kbuf;	h = (MPT_SCSI_HOST *)SChost->hostdata;	info_kbuf[0] = '\0';	mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);	info_kbuf[size-1] = '\0';	return info_kbuf;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/	static int max_qd = 1;#if 0static int index_log[128];static int index_ent = 0;static __inline__ void ADD_INDEX_LOG(int req_ent){	int i = index_ent++;	index_log[i & (128 - 1)] = req_ent;}#else#define ADD_INDEX_LOG(req_ent)	do { } while(0)#endif#ifdef	DROP_TEST#define DROP_IOC	1	/* IOC to force failures */#define DROP_TARGET	3	/* Target ID to force failures */#define	DROP_THIS_CMD	10000	/* iteration to drop command */static int dropCounter = 0;static int dropTestOK = 0;	/* num did good */static int dropTestBad = 0;	/* num did bad */static int dropTestNum = 0;	/* total = good + bad + incomplete */static int numTotCmds = 0;static MPT_FRAME_HDR *dropMfPtr = NULL;static int numTMrequested = 0;#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_put_msgframe - Wrapper routine to post message frame to F/W. *	@context: Call back context (ScsiDoneCtx, ScsiScanDvCtx)  *	@id: IOC id number  *	@mf: Pointer to message frame  * *	Handles the call to mptbase for posting request and queue depth  *	tracking. * *	Returns none. */static voidmptscsih_put_msgframe(int context, int id, MPT_FRAME_HDR *mf){	/* Main banana... */	atomic_inc(&queue_depth);	if (atomic_read(&queue_depth) > max_qd) {		max_qd = atomic_read(&queue_depth);		dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd));	}	mpt_put_msg_frame(context, id, mf);	return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. *	@SCpnt: Pointer to Scsi_Cmnd structure *	@done: Pointer SCSI mid-layer IO completion function * *	(linux Scsi_Host_Template.queuecommand routine) *	This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest *	from a linux Scsi_Cmnd request and send it to the IOC. * *	Returns 0. (rtn value discarded by linux scsi mid-layer) */intmptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){	MPT_SCSI_HOST		*hd;	MPT_FRAME_HDR		*mf;	SCSIIORequest_t		*pScsiReq;	VirtDevice		*pTarget;	MPT_DONE_Q		*buffer = NULL;	unsigned long		 flags;	int	 target;	int	 lun;	int	 datadir;	u32	 datalen;	u32	 scsictl;	u32	 scsidir;	u32	 qtag;	u32	 cmd_len;	int	 my_idx;	int	 ii;	int	 rc;	int	 did_errcode;	int	 issueCmd;	did_errcode = 0;	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;	target = SCpnt->target;	lun = SCpnt->lun;	SCpnt->scsi_done = done;	pTarget = hd->Targets[target];	dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));	/* 20000617 -sralston	 *  GRRRRR...  Shouldn't have to do this but...	 *  Do explicit check for REQUEST_SENSE and cached SenseData.	 *  If yes, return cached SenseData.	 */	if (SCpnt->cmnd[0] == REQUEST_SENSE) {		u8 *dest = NULL;		int sz;		if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_SENSE)) {			pTarget->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE;	//sjr-moved-here			if (!SCpnt->use_sg) {				dest = SCpnt->request_buffer;			} else {				struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;				if (sg)					dest = (u8 *)(ulong)sg_dma_address(sg);			}			if (dest) {				sz = MIN (SCSI_STD_SENSE_BYTES, SCpnt->request_bufflen);				memcpy(dest, pTarget->sense, sz);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)				SCpnt->resid = SCpnt->request_bufflen - sz;#endif				SCpnt->result = 0;				SCpnt->scsi_done(SCpnt);				//sjr-moved-up//pTarget->tflags &= ~MPT_TARGET_FLAGS_VALID_SENSE;				return 0;			}		}	}	if (hd->resetPending) {		/* Prevent new commands from being issued		 * while reloading the FW.		 */		did_errcode = 1;		goto did_error;	}	/*	 *  Put together a MPT SCSI request...	 */	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {		dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",				hd->ioc->name));		did_errcode = 2;		goto did_error;	}	pScsiReq = (SCSIIORequest_t *) mf;	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);	ADD_INDEX_LOG(my_idx);	/*	 *  The scsi layer should be handling this stuff	 *  (In 2.3.x it does -DaveM)	 */	/*  BUG FIX!  19991030 -sralston	 *    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...	 */	datadir = mptscsih_io_direction(SCpnt);	if (datadir < 0) {		datalen = SCpnt->request_bufflen;		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */	} else if (datadir > 0) {		datalen = SCpnt->request_bufflen;		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.	 */	qtag = MPI_SCSIIO_CONTROL_UNTAGGED;	if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)			&& (SCpnt->device->tagged_supported)) {		/*		 *  Some drives are too stupid to handle fairness issues		 *  with tagged queueing. We throw in the odd ordered		 *  tag to stop them starving themselves.		 */		if ((jiffies - hd->qtag_tick) > (5*HZ)) {			qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;			hd->qtag_tick = jiffies;		}		else			qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;	}	scsictl = scsidir | qtag;	/* Use the above information to set up the message frame	 */	pScsiReq->TargetID = target;	pScsiReq->Bus = hd->port;	pScsiReq->ChainOffset = 0;	pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;	pScsiReq->CDBLength = SCpnt->cmd_len;	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;	pScsiReq->Reserved = 0;	pScsiReq->MsgFlags = MPT_SCSIIO_MSG_FLAGS;	pScsiReq->LUN[0] = 0;	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.	 */	rc = SUCCESS;	if (datalen == 0) {		/* Add a NULL SGE */		mptscsih_AddNullSGE(pScsiReq);	} else {		/* Add a 32 or 64 bit SGE */		rc = mptscsih_Add32BitSGE(hd, SCpnt, pScsiReq, my_idx);	}	if (rc == SUCCESS) {		hd->ScsiLookup[my_idx] = SCpnt;		SCpnt->host_scribble = NULL;#ifdef	DROP_TEST		numTotCmds++;		/* If the IOC number and target match, increment		 * counter. If counter matches DROP_THIS, do not		 * issue command to FW to force a reset.		 * Save the MF pointer so we can free resources		 * when task mgmt completes.		 */		if ((hd->ioc->id == DROP_IOC) && (target == DROP_TARGET)) {			dropCounter++;

⌨️ 快捷键说明

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