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

📄 mptfc.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (!vdev) {		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",				hd->ioc->name, sizeof(VirtDevice));		return -ENOMEM;	}	sdev->hostdata = vdev;	vtarget = starget->hostdata;	if (vtarget->num_luns == 0) {		vtarget->ioc_id = hd->ioc->id;		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |		    		  MPT_TARGET_FLAGS_VALID_INQUIRY;		hd->Targets[sdev->id] = vtarget;	}	vdev->vtarget = vtarget;	vdev->lun = sdev->lun;	vtarget->num_luns++;#ifdef DMPT_DEBUG_FC	{	u64 nn, pn;	struct mptfc_rport_info *ri;	ri = *((struct mptfc_rport_info **)rport->dd_data);	pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;	nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;	dfcprintk ((MYIOC_s_INFO_FMT		"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "	        "CurrentTargetID %d, %x %llx %llx\n",		hd->ioc->name,		sdev->host->host_no,		vtarget->num_luns,		sdev->id, ri->pg0.CurrentTargetID,		ri->pg0.PortIdentifier,		(unsigned long long)pn,		(unsigned long long)nn));	}#endif	return 0;}static intmptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){	struct mptfc_rport_info	*ri;	struct fc_rport	*rport = starget_to_rport(scsi_target(SCpnt->device));	int		err;	err = fc_remote_port_chkready(rport);	if (unlikely(err)) {		SCpnt->result = err;		done(SCpnt);		return 0;	}	/* dd_data is null until finished adding target */	ri = *((struct mptfc_rport_info **)rport->dd_data);	if (unlikely(!ri)) {		dfcprintk ((MYIOC_s_INFO_FMT			"mptfc_qcmd.%d: %d:%d, dd_data is null.\n",			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,			SCpnt->device->id,SCpnt->device->lun));		SCpnt->result = DID_IMM_RETRY << 16;		done(SCpnt);		return 0;	}	err = mptscsih_qcmd(SCpnt,done);#ifdef DMPT_DEBUG_FC	if (unlikely(err)) {		dfcprintk ((MYIOC_s_INFO_FMT			"mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,			SCpnt->device->id,SCpnt->device->lun));	}#endif	return err;}static voidmptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum){	unsigned class = 0, cos = 0;	/* don't know what to do as only one scsi (fc) host was allocated */	if (portnum != 0)		return;	class = ioc->fc_port_page0[portnum].SupportedServiceClass;	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)		cos |= FC_COS_CLASS1;	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)		cos |= FC_COS_CLASS2;	if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)		cos |= FC_COS_CLASS3;	fc_host_node_name(ioc->sh) =	    	(u64)ioc->fc_port_page0[portnum].WWNN.High << 32		    | (u64)ioc->fc_port_page0[portnum].WWNN.Low;	fc_host_port_name(ioc->sh) =	    	(u64)ioc->fc_port_page0[portnum].WWPN.High << 32		    | (u64)ioc->fc_port_page0[portnum].WWPN.Low;	fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;	fc_host_supported_classes(ioc->sh) = cos;	fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;}static voidmptfc_rescan_devices(void *arg){	MPT_ADAPTER		*ioc = (MPT_ADAPTER *)arg;	int			ii;	int			work_to_do;	u64			pn;	unsigned long		flags;	struct mptfc_rport_info *ri;	do {		/* start by tagging all ports as missing */		list_for_each_entry(ri, &ioc->fc_rports, list) {			if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {				ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;			}		}		/*		 * now rescan devices known to adapter,		 * will reregister existing rports		 */		for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {			(void) mptbase_GetFcPortPage0(ioc, ii);			mptfc_init_host_attr(ioc,ii);	/* refresh */			mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);		}		/* delete devices still missing */		list_for_each_entry(ri, &ioc->fc_rports, list) {			/* if newly missing, delete it */			if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {				ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|					       MPT_RPORT_INFO_FLAGS_MISSING);				fc_remote_port_delete(ri->rport);	/* won't sleep */				ri->rport = NULL;				pn = (u64)ri->pg0.WWPN.High << 32 |				     (u64)ri->pg0.WWPN.Low;				dfcprintk ((MYIOC_s_INFO_FMT					"mptfc_rescan.%d: %llx deleted\n",					ioc->name,					ioc->sh->host_no,					(unsigned long long)pn));			}		}		/*		 * allow multiple passes as target state		 * might have changed during scan		 */		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);		if (ioc->fc_rescan_work_count > 2) 	/* only need one more */			ioc->fc_rescan_work_count = 2;		work_to_do = --ioc->fc_rescan_work_count;		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);	} while (work_to_do);}static intmptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id){	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	MPT_ADAPTER 		*ioc;	unsigned long		 flags;	int			 ii;	int			 numSGE = 0;	int			 scale;	int			 ioc_cap;	int			error=0;	int			r;	if ((r = mpt_attach(pdev,id)) != 0)		return r;	ioc = pci_get_drvdata(pdev);	ioc->DoneCtx = mptfcDoneCtx;	ioc->TaskCtx = mptfcTaskCtx;	ioc->InternalCtx = mptfcInternalCtx;	/*  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);		error = -ENODEV;		goto out_mptfc_probe;	}	if (!ioc->active) {		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",		  ioc->name);		error = -ENODEV;		goto out_mptfc_probe;	}	/*  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(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));	if (!sh) {		printk(MYIOC_s_WARN_FMT			"Unable to register controller with SCSI subsystem\n",			ioc->name);		error = -1;		goto out_mptfc_probe;        }	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);	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;	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;	}	spin_unlock_irqrestore(&ioc->FreeQlock, flags);	hd = (MPT_SCSI_HOST *) sh->hostdata;	hd->ioc = ioc;	/* SCSI needs scsi_cmnd lookup table!	 * (with size equal to req_depth*PtrSz!)	 */	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);	if (!hd->ScsiLookup) {		error = -ENOMEM;		goto out_mptfc_probe;	}	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",		 ioc->name, hd->ScsiLookup));	/* Allocate memory for the device structures.	 * A non-Null pointer at an offset	 * indicates a device exists.	 * max_id = 1 + maximum id (hosts.h)	 */	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);	if (!hd->Targets) {		error = -ENOMEM;		goto out_mptfc_probe;	}	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));	/* Clear the TM flags	 */	hd->tmPending = 0;	hd->tmState = TM_STATE_NONE;	hd->resetPending = 0;	hd->abortSCpnt = NULL;	/* Clear the pointer used to store	 * single-threaded commands, i.e., those	 * issued during a bus scan, dv and	 * configuration pages.	 */	hd->cmdPtr = NULL;	/* Initialize this SCSI Hosts' timers	 * To use, set the timer expires field	 * and add_timer	 */	init_timer(&hd->timer);	hd->timer.data = (unsigned long) hd;	hd->timer.function = mptscsih_timer_expired;	hd->mpt_pq_filter = mpt_pq_filter;	ddvprintk((MYIOC_s_INFO_FMT		"mpt_pq_filter %x\n",		ioc->name, 		mpt_pq_filter));	init_waitqueue_head(&hd->scandv_waitq);	hd->scandv_wait_done = 0;	hd->last_queue_full = 0;	sh->transportt = mptfc_transport_template;	error = scsi_add_host (sh, &ioc->pcidev->dev);	if(error) {		dprintk((KERN_ERR MYNAM		  "scsi_add_host failed\n"));		goto out_mptfc_probe;	}	/* initialize workqueue */	snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",		sh->host_no);	ioc->fc_rescan_work_q =		create_singlethread_workqueue(ioc->fc_rescan_work_q_name);	if (!ioc->fc_rescan_work_q)		goto out_mptfc_probe;	/*	 * scan for rports -	 *	by doing it via the workqueue, some locking is eliminated	 */	ioc->fc_rescan_work_count = 1;	queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);	flush_workqueue(ioc->fc_rescan_work_q);	return 0;out_mptfc_probe:	mptscsih_remove(pdev);	return error;}static struct pci_driver mptfc_driver = {	.name		= "mptfc",	.id_table	= mptfc_pci_table,	.probe		= mptfc_probe,	.remove		= __devexit_p(mptfc_remove),	.shutdown	= mptscsih_shutdown,#ifdef CONFIG_PM	.suspend	= mptscsih_suspend,	.resume		= mptscsih_resume,#endif};/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with *	linux scsi mid-layer. * *	Returns 0 for success, non-zero for failure. */static int __initmptfc_init(void){	int error;	show_mptmod_ver(my_NAME, my_VERSION);	/* sanity check module parameter */	if (mptfc_dev_loss_tmo == 0)		mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;	mptfc_transport_template =		fc_attach_transport(&mptfc_transport_functions);	if (!mptfc_transport_template)		return -ENODEV;	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {		devtverboseprintk((KERN_INFO MYNAM		  ": Registered for IOC event notifications\n"));	}	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {		dprintk((KERN_INFO MYNAM		  ": Registered for IOC reset notifications\n"));	}	error = pci_register_driver(&mptfc_driver);	if (error)		fc_release_transport(mptfc_transport_template);	return error;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptfc_remove - Removed fc infrastructure for devices *	@pdev: Pointer to pci_dev structure * */static void __devexitmptfc_remove(struct pci_dev *pdev){	MPT_ADAPTER		*ioc = pci_get_drvdata(pdev);	struct mptfc_rport_info	*p, *n;	struct workqueue_struct *work_q;	unsigned long		flags;	/* destroy workqueue */	if ((work_q=ioc->fc_rescan_work_q)) {		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);		ioc->fc_rescan_work_q = NULL;		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);		destroy_workqueue(work_q);	}	fc_remove_host(ioc->sh);	list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {		list_del(&p->list);		kfree(p);	}	mptscsih_remove(pdev);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptfc_exit - Unregisters MPT adapter(s) * */static void __exitmptfc_exit(void){	pci_unregister_driver(&mptfc_driver);	fc_release_transport(mptfc_transport_template);	mpt_reset_deregister(mptfcDoneCtx);	dprintk((KERN_INFO MYNAM	  ": Deregistered for IOC reset notifications\n"));	mpt_event_deregister(mptfcDoneCtx);	dprintk((KERN_INFO MYNAM	  ": Deregistered for IOC event notifications\n"));	mpt_deregister(mptfcInternalCtx);	mpt_deregister(mptfcTaskCtx);	mpt_deregister(mptfcDoneCtx);}module_init(mptfc_init);module_exit(mptfc_exit);

⌨️ 快捷键说明

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