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

📄 mptscsih.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
					    SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));			} else if (SCpnt->request_bufflen) {				scPrivate	*my_priv;						my_priv = (scPrivate *) &SCpnt->SCp;				pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,					   SCpnt->request_bufflen,					   scsi_to_pci_dma_dir(SCpnt->sc_data_direction));			}			SCpnt->result = DID_RESET << 16;			SCpnt->host_scribble = NULL;                        MPT_HOST_LOCK(flags);			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */                        MPT_HOST_UNLOCK(flags);			/* Free Chain buffers */			mptscsih_freeChainBuffers(hd, ii);			/* Free Message frames */			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);		}	}#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION	/* Clear untagged counting array */	for (ii= 0; ii < MPT_MAX_SCSI_DEVICES; ii++)		hd->ioc->spi_data.iocntr[ii] = 0;#endif	return;}#ifdef DROP_TEST/* 	mptscsih_flush_drop_test - Free resources and do callback if *		DROP_TEST enabled. * *	@hd: Pointer to a SCSI HOST structure * *	Returns: None. * *	Must be called while new I/Os are being queued. */static voidmptscsih_flush_drop_test (MPT_SCSI_HOST *hd){	Scsi_Cmnd	*sc;	unsigned long	 flags;	u16		 req_idx;	/* Free resources for the drop test MF	 * and chain buffers.	 */	if (dropMfPtr) {		req_idx = le16_to_cpu(dropMfPtr->u.frame.hwhdr.msgctxu.fld.req_idx);		sc = hd->ScsiLookup[req_idx];		if (sc == NULL) {			printk(MYIOC_s_ERR_FMT "Drop Test: NULL ScsiCmd ptr!\n",					ioc->name);		} else {			/* unmap OS resources, set status, do callback			 * free driver resources			 */			if (sc->use_sg) {				pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,					    sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));			} else if (sc->request_bufflen) {				scPrivate	*my_priv;				my_priv = (scPrivate *) &sc->SCp;				pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,					   sc->request_bufflen,					   scsi_to_pci_dma_dir(sc->sc_data_direction));			}			sc->host_scribble = NULL;			sc->result = DID_RESET << 16;			hd->ScsiLookup[req_idx] = NULL;			atomic_dec(&queue_depth);			MPT_HOST_LOCK(flags);			sc->scsi_done(sc);	/* Issue callback */			MPT_HOST_UNLOCK(flags);		}		mptscsih_freeChainBuffers(hd, req_idx);		mpt_free_msg_frame(ScsiDoneCtx, ioc->id, dropMfPtr);		printk(MYIOC_s_INFO_FMT "Free'd Dropped cmd (%p)\n",					hd->ioc->name, sc);		printk(MYIOC_s_INFO_FMT "mf (%p) reqidx (%4x)\n",					hd->ioc->name, dropMfPtr, req_idx);		printk(MYIOC_s_INFO_FMT "Num Tot (%d) Good (%d) Bad (%d) \n",				hd->ioc->name, dropTestNum,				dropTestOK, dropTestBad);	}	dropMfPtr = NULL;	return;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_initChainBuffers - Allocate memory for and initialize *	chain buffers, chain buffer control arrays and spinlock. *	@hd: Pointer to MPT_SCSI_HOST structure *	@init: If set, initialize the spin lock. */static intmptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init){	MPT_FRAME_HDR	*chain;	u8		*mem;	unsigned long	flags;	int		sz, ii, numChain;        /* Chain buffer allocations	 * Allocate and initialize tracker structures	 */	if (hd->ioc->req_sz <= 64)		numChain = MPT_SG_REQ_64_SCALE * hd->ioc->req_depth;	else if (hd->ioc->req_sz <= 96)		numChain = MPT_SG_REQ_96_SCALE * hd->ioc->req_depth;	else		numChain = MPT_SG_REQ_128_SCALE * hd->ioc->req_depth;	sz = numChain * sizeof(int);	if (hd->ReqToChain == NULL) {		mem = kmalloc(sz, GFP_ATOMIC);		if (mem == NULL)			return -1;		hd->ReqToChain = (int *) mem;	} else {		mem = (u8 *) hd->ReqToChain;	}	memset(mem, 0xFF, sz);	if (hd->ChainToChain == NULL) {		mem = kmalloc(sz, GFP_ATOMIC);		if (mem == NULL)			return -1;		hd->ChainToChain = (int *) mem;	} else {		mem = (u8 *) hd->ChainToChain;	}	memset(mem, 0xFF, sz);	if (hd->ChainBuffer == NULL) {		/* Allocate free chain buffer pool		 */		sz = numChain * hd->ioc->req_sz;		mem = pci_alloc_consistent(hd->ioc->pcidev, sz, &hd->ChainBufferDMA);		if (mem == NULL)			return -1;		hd->ChainBuffer = (u8*)mem;	} else {		mem = (u8 *) hd->ChainBuffer;	}	memset(mem, 0, sz);	dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",		 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, sz));	/* Initialize the free chain Q.	 */	if (init) {		spin_lock_init(&hd->FreeChainQlock);	}	spin_lock_irqsave (&hd->FreeChainQlock, flags);	Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);	/* Post the chain buffers to the FreeChainQ.	 */	mem = (u8 *)hd->ChainBuffer;	for (ii=0; ii < numChain; ii++) {		chain = (MPT_FRAME_HDR *) mem;		Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);		mem += hd->ioc->req_sz;	}	spin_unlock_irqrestore(&hd->FreeChainQlock, flags);	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Hack! It might be nice to report if a device is returning QUEUE_FULL *  but maybe not each and every time... */static long last_queue_full = 0;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_report_queue_full - Report QUEUE_FULL status returned *	from a SCSI target device. *	@sc: Pointer to Scsi_Cmnd structure *	@pScsiReply: Pointer to SCSIIOReply_t *	@pScsiReq: Pointer to original SCSI request * *	This routine periodically reports QUEUE_FULL status returned from a *	SCSI target device.  It reports this to the console via kernel *	printk() API call, not more than once every 10 seconds. */static voidmptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq){	long time = jiffies;	if (time - last_queue_full > 10 * HZ) {		char *ioc_str = "ioc?";		if (sc->host != NULL && sc->host->hostdata != NULL)			ioc_str = ((MPT_SCSI_HOST *)sc->host->hostdata)->ioc->name;		printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",				ioc_str, 0, sc->target, sc->lun);		last_queue_full = time;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static int BeenHereDoneThat = 0;/*  SCSI host fops start here...  *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with *	linux scsi mid-layer. *	@tpnt: Pointer to Scsi_Host_Template structure * *	(linux Scsi_Host_Template.detect routine) * *	Returns number of SCSI host adapters that were successfully *	registered with the linux scsi mid-layer via the scsi_register() *	API call. */intmptscsih_detect(Scsi_Host_Template *tpnt){	struct Scsi_Host	*sh = NULL;	MPT_SCSI_HOST		*hd = NULL;	MPT_ADAPTER		*this;	MPT_DONE_Q		*freedoneQ;	unsigned long		 flags;	int			 sz, ii;	int			 numSGE = 0;	int			 scale;	u8			*mem;	if (! BeenHereDoneThat++) {		show_mptmod_ver(my_NAME, my_VERSION);		ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);		ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);		ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);#ifndef MPT_SCSI_USE_NEW_EH		spin_lock_init(&mytaskQ_lock);#endif		if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {			dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));		} else {			/* FIXME! */		}		if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {			dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));		} else {			/* FIXME! */		}	}	dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));#ifdef MODULE	/* Evaluate the command line arguments, if any */	if (mptscsih)		mptscsih_setup(mptscsih);#endif#ifndef MPT_SCSI_USE_NEW_EH	atomic_set(&mpt_taskQdepth, 0);#endif	this = mpt_adapter_find_first();	while (this != NULL) {		int	 portnum;		for (portnum=0; portnum < this->facts.NumberOfPorts; portnum++) {			/* 20010215 -sralston			 *  Added sanity check on SCSI Initiator-mode enabled			 *  for this MPT adapter.			 */			if (!(this->pfacts[portnum].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {				printk(MYIOC_s_WARN_FMT "Skipping because SCSI Initiator mode is NOT enabled!\n",						this->name);				continue;			}			/* 20010202 -sralston			 *  Added sanity check on readiness of the MPT adapter.			 */			if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {				printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n",						this->name);				continue;			}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)			tpnt->proc_dir = &proc_mpt_scsihost;#endif			sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));			if (sh != NULL) {				save_flags(flags);				cli();				sh->io_port = 0;				sh->n_io_port = 0;				sh->irq = 0;				/* Yikes!  This is important!				 * Otherwise, by default, linux				 * only scans target IDs 0-7!				 * pfactsN->MaxDevices unreliable				 * (not supported in early				 *	versions of the FW).				 * max_id = 1 + actual max id,				 * max_lun = 1 + actual last lun,				 *	see hosts.h :o(				 */				if ((int)this->chip_type > (int)FC929)					sh->max_id = MPT_MAX_SCSI_DEVICES;				else {					/* For FC, increase the queue depth					 * from MPT_SCSI_CAN_QUEUE (31)					 * to MPT_FC_CAN_QUEUE (63).					 */					sh->can_queue = MPT_FC_CAN_QUEUE;					sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;				}				sh->max_lun = MPT_LAST_LUN + 1;				sh->this_id = this->pfacts[portnum].PortSCSIID;				/* OS entry to allow host drivers to force				 * a queue depth on a per device basis.				 */				sh->select_queue_depths = mptscsih_select_queue_depths;				/* Verify that we won't exceed the maximum				 * number of chain buffers				 * We can optimize:  ZZ = req_sz/sizeof(SGE)				 * For 32bit SGE's:				 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ				 *               + (req_sz - 64)/sizeof(SGE)				 * A slightly different algorithm is required for				 * 64bit SGEs.				 */				scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32));				if (sizeof(dma_addr_t) == sizeof(u64)) {					numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale +						(this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));				} else {					numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +						(this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));				} 				if (numSGE < sh->sg_tablesize) {					/* Reset this value */					dprintk((MYIOC_s_INFO_FMT						 "Resetting sg_tablesize to %d from %d\n",						 this->name, numSGE, sh->sg_tablesize));					sh->sg_tablesize = numSGE;				}				/* Set the pci device pointer in Scsi_Host structure.				 */				scsi_set_pci_device(sh, this->pcidev);				restore_flags(flags);				hd = (MPT_SCSI_HOST *) sh->hostdata;				hd->ioc = this;				if ((int)this->chip_type > (int)FC929)					hd->is_spi = 1;				if (DmpService &&				    (this->chip_type == FC919 || this->chip_type == FC929))					hd->is_multipath = 1;				hd->port = 0;		/* FIXME! */				/* SCSI needs Scsi_Cmnd lookup table!				 * (with size equal to req_depth*PtrSz!)				 */				sz = hd->ioc->req_depth * sizeof(void *);				mem = kmalloc(sz, GFP_ATOMIC);				if (mem == NULL)					goto done;				memset(mem, 0, sz);				hd->ScsiLookup = (struct scsi_cmnd **) mem;				dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",					 this->name, hd->ScsiLookup, sz));				if (mptscsih_initChainBuffers(hd, 1) < 0)					goto done;				/* Allocate memory for free and doneQ's				 */				sz = sh->can_queue * sizeof(MPT_DONE_Q);				mem = kmalloc(sz, GFP_ATOMIC);				if (mem == NULL)					goto done;				memset(mem, 0xFF, sz);				hd->memQ = mem;				/* Initialize the free, done and pending Qs.				 */				Q_INIT(&hd->freeQ, MPT_DONE_Q);				Q_INIT(&hd->doneQ, MPT_DONE_Q);				Q_INIT(&hd->pendingQ, MPT_DONE_Q);				spin_lock_init(&hd->freedoneQlock);				mem = hd->memQ;				for (ii=0; ii < sh->can_queue; ii++) {					freedoneQ = (MPT_DONE_Q *) mem;					Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);					mem += sizeof(MPT_DONE_Q);				}				/* Initialize this Scsi_Host				 * internal task Q.				 */				Q_INIT(&hd->taskQ, MPT_FRAME_HDR);				hd->taskQcnt = 0;				/* Allocate memory for the device structures.				 * A non-Null pointer at an offset				 * indicates a device exists.				 * max_id = 1 + maximum id (hosts.h)				 */				sz = sh->max_id * sizeof(void *);				mem = kmalloc(sz, GFP_ATOMIC);				if (mem == NULL)					goto done;				memset(mem, 0, sz);				hd->Targets = (VirtDevice **) mem;				dprintk((KERN_INFO "  Targets @ %p, sz=%d\n", hd->Targets, sz));				/* Clear the TM flags				 */				hd->tmPending = 0;#ifdef MPT_SCSI_USE_NEW_EH				hd->tmState = TM_STATE_NONE;#endif				hd->resetPending = 0;

⌨️ 快捷键说明

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