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

📄 mptscsih.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct scsi_cmnd	*SCpnt;	MPT_FRAME_HDR	*mf;	MPT_DONE_Q	*buffer;	int		 ii;	int		 max = hd->ioc->req_depth;	unsigned long	 flags;	dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));	for (ii= 0; ii < max; ii++) {		if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {			/* Command found.			 */			/* Search pendingQ, if found,			 * delete from Q.			 */			mptscsih_search_pendingQ(hd, ii);			/* Null ScsiLookup index			 */			hd->ScsiLookup[ii] = NULL;			mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);			dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",					mf, SCpnt));			/* Set status, free OS resources (SG DMA buffers)			 * Do OS callback			 * Free driver resources (chain, msg buffers)			 */			if (scsi_device_online(SCpnt->device)) {				if (SCpnt->use_sg) {					pci_unmap_sg(hd->ioc->pcidev,						(struct scatterlist *) SCpnt->request_buffer,						SCpnt->use_sg,						SCpnt->sc_data_direction);				} else if (SCpnt->request_bufflen) {					pci_unmap_single(hd->ioc->pcidev,						SCpnt->SCp.dma_handle,						SCpnt->request_bufflen,						SCpnt->sc_data_direction);				}			}			SCpnt->result = DID_RESET << 16;			SCpnt->host_scribble = NULL;			/* Free Chain buffers */			mptscsih_freeChainBuffers(hd, ii);			/* Free Message frames */			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);#if 1			/* Post to doneQ, do not reply until POST phase			 * of reset handler....prevents new commands from			 * being queued.			 */			spin_lock_irqsave(&hd->freedoneQlock, flags);			if (!Q_IS_EMPTY(&hd->freeQ)) {				buffer = hd->freeQ.head;				Q_DEL_ITEM(buffer);				/* Set the struct scsi_cmnd pointer				 */				buffer->argp = (void *)SCpnt;				/* Add to the doneQ				 */				Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);				spin_unlock_irqrestore(&hd->freedoneQlock, flags);			} else {				spin_unlock_irqrestore(&hd->freedoneQlock, flags);				SCpnt->scsi_done(SCpnt);			}#else			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */#endif		}	}	return;}/* *	mptscsih_search_running_cmds - Delete any commands associated *		with the specified target and lun. Function called only *		when a lun is disable by mid-layer. *		Do NOT access the referenced scsi_cmnd structure or *		members. Will cause either a paging or NULL ptr error. *	@hd: Pointer to a SCSI HOST structure *	@target: target id *	@lun: lun * *	Returns: None. * *	Called from slave_destroy. */static voidmptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun){	SCSIIORequest_t	*mf = NULL;	int		 ii;	int		 max = hd->ioc->req_depth;	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",			target, lun, max));	for (ii=0; ii < max; ii++) {		if (hd->ScsiLookup[ii] != NULL) {			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);			dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",					hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));			if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))				continue;			/* Cleanup			 */			hd->ScsiLookup[ii] = NULL;			mptscsih_freeChainBuffers(hd, ii);			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, (MPT_FRAME_HDR *)mf);		}	}	return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	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, num_chain;	int 		scale, num_sge;	/* chain buffer allocation done from PrimeIocFifos */		if (hd->ioc->fifo_pool == NULL) 		return -1;		hd->ChainBuffer = hd->ioc->chain_alloc;	hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;		dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",		 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));			/* ReqToChain size must equal the req_depth	 * index = req_idx	 */	if (hd->ReqToChain == NULL) {		sz = hd->ioc->req_depth * sizeof(int);		mem = kmalloc(sz, GFP_ATOMIC);		if (mem == NULL)			return -1;		hd->ReqToChain = (int *) mem;	}	for (ii = 0; ii < hd->ioc->req_depth; ii++)		hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;	/* ChainToChain size must equal the total number	 * of chain buffers to be allocated.	 * index = chain_idx	 *	 * Calculate the number of chain buffers needed(plus 1) per I/O	 * then multiply the the maximum number of simultaneous cmds	 *	 * num_sge = num sge in request frame + last chain buffer	 * scale = num sge per chain buffer if no chain element	 */	scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));	if (sizeof(dma_addr_t) == sizeof(u64))		num_sge =  scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));	else		num_sge =  1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));	num_chain = 1;	while (hd->max_sge - num_sge > 0) {		num_chain++;		num_sge += (scale - 1);	}	num_chain++;	if ((int) hd->ioc->chip_type > (int) FC929)		num_chain *= MPT_SCSI_CAN_QUEUE;	else		num_chain *= MPT_FC_CAN_QUEUE;	hd->num_chain = num_chain;	sz = num_chain * sizeof(int);	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);	/* 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 < num_chain; 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(struct 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->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)			ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;		dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",				ioc_str, 0, sc->device->id, sc->device->lun));		last_queue_full = time;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static char *info_kbuf = NULL;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_probe - Installs scsi devices per bus. *	@pdev: Pointer to pci_dev structure * *	Returns 0 for success, non-zero for failure. * */static intmptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id){	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);	MPT_DONE_Q		*freedoneQ;	unsigned long		 flags;	int			 sz, ii;	int			 numSGE = 0;	int			 scale;	int			 ioc_cap;	u8			*mem;	int			error=0;	/* 20010202 -sralston	 *  Added sanity check on readiness of the MPT adapter.	 */	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {		printk(MYIOC_s_WARN_FMT		  "Skipping because it's not operational!\n",		  ioc->name);		return -ENODEV;	}	if (!ioc->active) {		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",		  ioc->name);		return -ENODEV;	}	/*  Sanity check - ensure at least 1 port is INITIATOR capable	 */	ioc_cap = 0;	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {		if (ioc->pfacts[ii].ProtocolFlags &		    MPI_PORTFACTS_PROTOCOL_INITIATOR)			ioc_cap ++;	}	if (!ioc_cap) {		printk(MYIOC_s_WARN_FMT			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",			ioc->name, ioc);		return -ENODEV;	}	sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));        	if (!sh) {		printk(MYIOC_s_WARN_FMT			"Unable to register controller with SCSI subsystem\n",			ioc->name);                return -1;        }		spin_lock_irqsave(&ioc->FreeQlock, flags);	/* Attach the SCSI Host to the IOC structure	 */	ioc->sh = sh;	sh->io_port = 0;	sh->n_io_port = 0;	sh->irq = 0;	/* set 16 byte cdb's */	sh->max_cmd_len = 16;	/* 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)ioc->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->max_channel = 0;	sh->this_id = ioc->pfacts[0].PortSCSIID;			/* Required entry.	 */	sh->unique_id = ioc->id;	/* 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 = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));	if (sizeof(dma_addr_t) == sizeof(u64)) {		numSGE = (scale - 1) *		  (ioc->facts.MaxChainDepth-1) + scale +		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +		  sizeof(u32));	} else {		numSGE = 1 + (scale - 1) *		  (ioc->facts.MaxChainDepth-1) + scale +		  (ioc->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",		  ioc->name, numSGE, sh->sg_tablesize));		sh->sg_tablesize = numSGE;	}	/* Set the pci device pointer in Scsi_Host structure.	 */	scsi_set_device(sh, &ioc->pcidev->dev);	spin_unlock_irqrestore(&ioc->FreeQlock, flags);	hd = (MPT_SCSI_HOST *) sh->hostdata;	hd->ioc = ioc;	hd->max_sge = sh->sg_tablesize;	if ((int)ioc->chip_type > (int)FC929)	hd->is_spi = 1;	if (DmpService && (ioc->chip_type == FC919 ||	  ioc->chip_type == FC929)) {		hd->is_multipath = 1;	}	/* 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) {		error = -ENOMEM;		goto mptscsih_probe_failed;	}	memset(mem, 0, sz);	hd->ScsiLookup = (struct scsi_cmnd **) mem;	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",		 ioc->name, hd->ScsiLookup, sz));			if (mptscsih_initChainBuffers(hd, 1) < 0) {		error = -EINVAL;		goto mptscsih_probe_failed;	}	/* Allocate memory for free and doneQ's	 */	sz = sh->can_queue * sizeof(MPT_DONE_Q);	mem = kmalloc(sz, GFP_ATOMIC);	if (mem == NULL) {		error = -ENOMEM;		goto mptscsih_probe_failed;	}	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);

⌨️ 快捷键说明

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