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

📄 mptscsih.c

📁 ARM S3C2410 linux2.4 内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	int count = 0;	int list_sz;	dslprintk((KERN_INFO MYNAM ": spinlock#1\n"));	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);	list_sz = mpt_scsih_taskQ_cnt;	if (! Q_IS_EMPTY(&mpt_scsih_taskQ)) {		mf = mpt_scsih_taskQ.head;		do {			count++;			if (mf->u.frame.linkage.argp1 == sc &&			    mf->u.frame.linkage.arg1 == task_type) {				if (remove) {					Q_DEL_ITEM(&mf->u.frame.linkage);					mpt_scsih_taskQ_cnt--;				}				break;			}		} while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&mpt_scsih_taskQ);		if (mf == (MPT_FRAME_HDR*)&mpt_scsih_taskQ) {			mf = NULL;		}	}	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);	if (list_sz) {		dprintk((KERN_INFO MYNAM ": search_taskQ(%d,%p,%d) results=%p (%sFOUND%s)!\n",				   remove, sc, task_type,				   mf,				   mf ? "" : "NOT_",				   (mf && remove) ? "+REMOVED" : "" ));		dprintk((KERN_INFO MYNAM ": (searched thru %d of %d items on taskQ)\n",				   count,				   list_sz ));	}	return mf;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Hack!  I'd like 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) {		printk(KERN_WARNING MYNAM ": Device reported QUEUE_FULL!  SCSI bus:target:lun = %d:%d:%d\n",				0, sc->target, sc->lun);		last_queue_full = time;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static int BeenHereDoneThat = 0;/*  SCSI 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;	unsigned long		 flags;	int			 sz;	u8			*mem;	if (! BeenHereDoneThat++) {		show_mptmod_ver(my_NAME, my_VERSION);		if ((ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER)) <= 0) {			printk(KERN_ERR MYNAM ": Failed to register callback1 with MPT base driver\n");			return mpt_scsi_hosts;		}		if ((ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER)) <= 0) {			printk(KERN_ERR MYNAM ": Failed to register callback2 with MPT base driver\n");			return mpt_scsi_hosts;		}#ifndef MPT_SCSI_USE_NEW_EH		Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);		spin_lock_init(&mpt_scsih_taskQ_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"));	this = mpt_adapter_find_first();	while (this != NULL) {		/* FIXME!  Multi-port (aka FC929) support...		 * for (i = 0; i < this->facts.NumberOfPorts; i++)		 */		/* 20010215 -sralston		 *  Added sanity check on SCSI Initiator-mode enabled		 *  for this MPT adapter.		 */		if (!(this->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {			printk(KERN_ERR MYNAM ": Skipping %s because SCSI Initiator mode is NOT enabled!\n",					this->name);			this = mpt_adapter_find_next(this);			continue;		}		/* 20010202 -sralston		 *  Added sanity check on readiness of the MPT adapter.		 */		if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {			printk(KERN_ERR MYNAM ": ERROR - Skipping %s because it's not operational!\n",					this->name);			this = mpt_adapter_find_next(this);			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!			 *			 * BUG FIX!  20010618 -sralston & pdelaney			 * FC919 testing was encountering "duplicate" FC devices,			 * as it turns out because the 919 was returning 512			 * for PortFacts.MaxDevices, causing a wraparound effect			 * in SCSI IO requests.  So instead of using:			 *     sh->max_id = this->pfacts[0].MaxDevices - 1			 * we'll use a definitive max here.			 */			sh->max_id = MPT_MAX_FC_DEVICES;			sh->this_id = this->pfacts[0].PortSCSIID;			restore_flags(flags);			hd = (MPT_SCSI_HOST *) sh->hostdata;			hd->ioc = this;			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_KERNEL);			if (mem == NULL)				return mpt_scsi_hosts;			memset(mem, 0, sz);			hd->ScsiLookup = (struct scsi_cmnd **) mem;			dprintk((KERN_INFO MYNAM ": ScsiLookup @ %p, sz=%d\n",				 hd->ScsiLookup, sz));			/* SCSI also needs SG buckets/hunk management!			 * (with size equal to N * req_sz * req_depth!)			 * (where N is number of SG buckets per hunk)			 */			sz = MPT_SG_BUCKETS_PER_HUNK * hd->ioc->req_sz * hd->ioc->req_depth;			mem = pci_alloc_consistent(hd->ioc->pcidev, sz,						   &hd->SgHunksDMA);			if (mem == NULL)				return mpt_scsi_hosts;			memset(mem, 0, sz);			hd->SgHunks = (u8*)mem;			dprintk((KERN_INFO MYNAM ": SgHunks    @ %p(%08x), sz=%d\n",				 hd->SgHunks, hd->SgHunksDMA, sz));			hd->qtag_tick = jiffies;			this->sh = sh;			mpt_scsi_hosts++;		}		this = mpt_adapter_find_next(this);	}	return mpt_scsi_hosts;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/    static char *info_kbuf = NULL;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_release - Unregister SCSI host from linux scsi mid-layer *	@host: Pointer to Scsi_Host structure * *	(linux Scsi_Host_Template.release routine) *	This routine releases all resources associated with the SCSI host *	adapter. * *	Returns 0 for success. */intmptscsih_release(struct Scsi_Host *host){	MPT_SCSI_HOST	*hd;#ifndef MPT_SCSI_USE_NEW_EH	unsigned long	 flags;	spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);	if (mpt_scsih_taskQ_bh_active) {		int count = 10 * HZ;		dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));		/* Zap the taskQ! */		Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);		spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);		while(mpt_scsih_taskQ_bh_active && --count) {			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(1);		}		if (!count)			printk(KERN_ERR MYNAM ": ERROR! TaskMgmt thread still active!\n");	}	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);#endif	hd = (MPT_SCSI_HOST *) host->hostdata;	if (hd != NULL) {		int sz1, sz2;		sz1 = sz2 = 0;		if (hd->ScsiLookup != NULL) {			sz1 = hd->ioc->req_depth * sizeof(void *);			kfree(hd->ScsiLookup);			hd->ScsiLookup = NULL;		}		if (hd->SgHunks != NULL) {			sz2 = MPT_SG_BUCKETS_PER_HUNK * hd->ioc->req_sz * hd->ioc->req_depth;			pci_free_consistent(hd->ioc->pcidev, sz2,					    hd->SgHunks, hd->SgHunksDMA);			hd->SgHunks = NULL;		}		dprintk((KERN_INFO MYNAM ": Free'd ScsiLookup (%d) and SgHunks (%d) memory\n", sz1, sz2));	}	if (mpt_scsi_hosts) {		if (--mpt_scsi_hosts == 0) {#if 0			mptscsih_flush_pending();#endif			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(ScsiDoneCtx);			mpt_deregister(ScsiTaskCtx);			if (info_kbuf != NULL)				kfree(info_kbuf);		}	}	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	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;#ifdef MPT_DEBUG	static int max_sges = 0;	static int max_xfer = 0;#endif#if 0	static int max_num_sges = 0;	static int max_sgent_len = 0;#endif#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/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	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 *)){	struct Scsi_Host	*host;	MPT_SCSI_HOST		*hd;	MPT_FRAME_HDR		*mf;	SCSIIORequest_t		*pScsiReq;	int	 datadir;	u32	 len;	u32	 sgdir;	u32	 scsictl;	u32	 scsidir;	u32	 qtag;	u32	*mptr;	int	 sge_spill1;	int	 frm_sz;	int	 sges_left;	u32	 chain_offset;	int	 my_idx;	int	 i;	dmfprintk((KERN_INFO MYNAM "_qcmd: SCpnt=%p, done()=%p\n",		    SCpnt, done));	host = SCpnt->host;	hd = (MPT_SCSI_HOST *) host->hostdata;	#if 0	if (host->host_busy >= 60) {		MPT_ADAPTER *ioc = hd->ioc;		u16 pci_command, pci_status;		/* The IOC is probably hung, investigate status. */		printk("MPI: IOC probably hung IOCSTAT[%08x] INTSTAT[%08x] REPLYFIFO[%08x]\n",		       readl(&ioc->chip.fc9xx->DoorbellValue),		       readl(&ioc->chip.fc9xx->IntStatus),		       readl(&ioc->chip.fc9xx->ReplyFifo));		pci_read_config_word(ioc->pcidev, PCI_COMMAND, &pci_command);		pci_read_config_word(ioc->pcidev, PCI_STATUS, &pci_status);		printk("MPI: PCI command[%04x] status[%04x]\n", pci_command, pci_status);		{			/* DUMP req index logger. */			int begin, end;			begin = (index_ent - 65) & (128 - 1);			end = index_ent & (128 - 1);			printk("MPI: REQ_INDEX_HIST[");			while (begin != end) {				printk("(%04x)", index_log[begin]);				begin = (begin + 1) & (128 - 1);			}			printk("\n");		}		sti();		while(1)			barrier();	}#endif	SCpnt->scsi_done = 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.	 */#ifdef MPT_SCSI_CACHE_AUTOSENSE	{		MPT_SCSI_DEV	*mpt_sdev;		mpt_sdev = (MPT_SCSI_DEV *) SCpnt->device->hostdata;		if (mpt_sdev && SCpnt->cmnd[0] == REQUEST_SENSE) {			u8 *dest = NULL;			if (!SCpnt->use_sg)				dest = SCpnt->request_buffer;			else {				struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;

⌨️ 快捷键说明

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