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

📄 mptfc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)		speed |= FC_PORTSPEED_4GBIT;	if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)		speed |= FC_PORTSPEED_10GBIT;	fc_host_supported_speeds(sh) = speed;	port_state = FC_PORTSTATE_UNKNOWN;	if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)		port_state = FC_PORTSTATE_ONLINE;	else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)		port_state = FC_PORTSTATE_LINKDOWN;	fc_host_port_state(sh) = port_state;	port_type = FC_PORTTYPE_UNKNOWN;	if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)		port_type = FC_PORTTYPE_PTP;	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)		port_type = FC_PORTTYPE_LPORT;	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)		port_type = FC_PORTTYPE_NLPORT;	else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)		port_type = FC_PORTTYPE_NPORT;	fc_host_port_type(sh) = port_type;	fc_host_fabric_name(sh) =	    (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?		(u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :		(u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;}static voidmptfc_link_status_change(struct work_struct *work){	MPT_ADAPTER             *ioc =		container_of(work, MPT_ADAPTER, fc_rescan_work);	int ii;	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++)		(void) mptfc_GetFcPortPage0(ioc, ii);}static voidmptfc_setup_reset(struct work_struct *work){	MPT_ADAPTER		*ioc =		container_of(work, MPT_ADAPTER, fc_setup_reset_work);	u64			pn;	struct mptfc_rport_info *ri;	/* reset about to happen, delete (block) all rports */	list_for_each_entry(ri, &ioc->fc_rports, list) {		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {			ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;			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 (ioc, printk(MYIOC_s_DEBUG_FMT				"mptfc_setup_reset.%d: %llx deleted\n",				ioc->name,				ioc->sh->host_no,				(unsigned long long)pn));		}	}}static voidmptfc_rescan_devices(struct work_struct *work){	MPT_ADAPTER		*ioc =		container_of(work, MPT_ADAPTER, fc_rescan_work);	int			ii;	u64			pn;	struct mptfc_rport_info *ri;	/* 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) mptfc_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 (ioc, printk(MYIOC_s_DEBUG_FMT				"mptfc_rescan.%d: %llx deleted\n",				ioc->name,				ioc->sh->host_no,				(unsigned long long)pn));		}	}}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 0;	}	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;        }	spin_lock_init(&ioc->fc_rescan_work_lock);	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);	INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);	INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change);	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 = ioc->pfacts->MaxDevices;	sh->max_lun = max_lun;	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(ioc, printk(MYIOC_s_DEBUG_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 = shost_priv(sh);	hd->ioc = ioc;	/* SCSI needs scsi_cmnd lookup table!	 * (with size equal to req_depth*PtrSz!)	 */	ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);	if (!ioc->ScsiLookup) {		error = -ENOMEM;		goto out_mptfc_probe;	}	spin_lock_init(&ioc->scsi_lookup_lock);	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",		 ioc->name, ioc->ScsiLookup));	/* 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;	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(ioc, printk(MYIOC_s_ERR_FMT		  "scsi_add_host failed\n", ioc->name));		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;	/*	 *  Pre-fetch FC port WWN and stuff...	 *  (FCPortPage0_t stuff)	 */	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {		(void) mptfc_GetFcPortPage0(ioc, ii);	}	mptfc_SetFcPortPage1_defaults(ioc);	/*	 * scan for rports -	 *	by doing it via the workqueue, some locking is eliminated	 */	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};static intmptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply){	MPT_SCSI_HOST *hd;	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;	unsigned long flags;	int rc=1;	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",			ioc->name, event));	if (ioc->sh == NULL ||		((hd = shost_priv(ioc->sh)) == NULL))		return 1;	switch (event) {	case MPI_EVENT_RESCAN:		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);		if (ioc->fc_rescan_work_q) {			queue_work(ioc->fc_rescan_work_q,				   &ioc->fc_rescan_work);		}		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);		break;	case MPI_EVENT_LINK_STATUS_CHANGE:		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);		if (ioc->fc_rescan_work_q) {			queue_work(ioc->fc_rescan_work_q,				   &ioc->fc_lsc_work);		}		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);		break;	default:		rc = mptscsih_event_process(ioc,pEvReply);		break;	}	return rc;}static intmptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase){	int		rc;	unsigned long	flags;	rc = mptscsih_ioc_reset(ioc,reset_phase);	if (rc == 0)		return rc;	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT		": IOC %s_reset routed to FC host driver!\n",ioc->name,		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));	if (reset_phase == MPT_IOC_SETUP_RESET) {		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);		if (ioc->fc_rescan_work_q) {			queue_work(ioc->fc_rescan_work_q,				   &ioc->fc_setup_reset_work);		}		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);	}	else if (reset_phase == MPT_IOC_PRE_RESET) {	}	else {	/* MPT_IOC_POST_RESET */		mptfc_SetFcPortPage1_defaults(ioc);		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);		if (ioc->fc_rescan_work_q) {			queue_work(ioc->fc_rescan_work_q,				   &ioc->fc_rescan_work);		}		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);	}	return 1;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with 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 parameters */	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);	mpt_event_register(mptfcDoneCtx, mptfc_event_process);	mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset);	error = pci_register_driver(&mptfc_driver);	if (error)		fc_release_transport(mptfc_transport_template);	return error;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptfc_remove - Remove 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;	int			ii;	/* 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);	}	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {		if (ioc->fc_data.fc_port_page1[ii].data) {			pci_free_consistent(ioc->pcidev,				ioc->fc_data.fc_port_page1[ii].pg_sz,				(u8 *) ioc->fc_data.fc_port_page1[ii].data,				ioc->fc_data.fc_port_page1[ii].dma);			ioc->fc_data.fc_port_page1[ii].data = NULL;		}	}	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);	mpt_event_deregister(mptfcDoneCtx);	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 + -