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

📄 lpfc_init.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	spin_unlock_irq(phba->host->host_lock);	return 0;}static int __devinitlpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid){	struct Scsi_Host *host;	struct lpfc_hba  *phba;	struct lpfc_sli  *psli;	struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;	unsigned long bar0map_len, bar2map_len;	int error = -ENODEV, retval;	int i;	uint16_t iotag;	if (pci_enable_device(pdev))		goto out;	if (pci_request_regions(pdev, LPFC_DRIVER_NAME))		goto out_disable_device;	host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));	if (!host)		goto out_release_regions;	phba = (struct lpfc_hba*)host->hostdata;	memset(phba, 0, sizeof (struct lpfc_hba));	phba->host = host;	phba->fc_flag |= FC_LOADING;	phba->pcidev = pdev;	/* Assign an unused board number */	if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))		goto out_put_host;	error = idr_get_new(&lpfc_hba_index, NULL, &phba->brd_no);	if (error)		goto out_put_host;	host->unique_id = phba->brd_no;	INIT_LIST_HEAD(&phba->ctrspbuflist);	INIT_LIST_HEAD(&phba->rnidrspbuflist);	INIT_LIST_HEAD(&phba->freebufList);	/* Initialize timers used by driver */	init_timer(&phba->fc_estabtmo);	phba->fc_estabtmo.function = lpfc_establish_link_tmo;	phba->fc_estabtmo.data = (unsigned long)phba;	init_timer(&phba->fc_disctmo);	phba->fc_disctmo.function = lpfc_disc_timeout;	phba->fc_disctmo.data = (unsigned long)phba;	init_timer(&phba->fc_fdmitmo);	phba->fc_fdmitmo.function = lpfc_fdmi_tmo;	phba->fc_fdmitmo.data = (unsigned long)phba;	init_timer(&phba->els_tmofunc);	phba->els_tmofunc.function = lpfc_els_timeout;	phba->els_tmofunc.data = (unsigned long)phba;	psli = &phba->sli;	init_timer(&psli->mbox_tmo);	psli->mbox_tmo.function = lpfc_mbox_timeout;	psli->mbox_tmo.data = (unsigned long)phba;	/*	 * Get all the module params for configuring this host and then	 * establish the host parameters.	 */	lpfc_get_cfgparam(phba);	host->max_id = LPFC_MAX_TARGET;	host->max_lun = phba->cfg_max_luns;	host->this_id = -1;	/* Initialize all internally managed lists. */	INIT_LIST_HEAD(&phba->fc_nlpmap_list);	INIT_LIST_HEAD(&phba->fc_nlpunmap_list);	INIT_LIST_HEAD(&phba->fc_unused_list);	INIT_LIST_HEAD(&phba->fc_plogi_list);	INIT_LIST_HEAD(&phba->fc_adisc_list);	INIT_LIST_HEAD(&phba->fc_reglogin_list);	INIT_LIST_HEAD(&phba->fc_prli_list);	INIT_LIST_HEAD(&phba->fc_npr_list);	pci_set_master(pdev);	retval = pci_set_mwi(pdev);	if (retval)		dev_printk(KERN_WARNING, &pdev->dev,			   "Warning: pci_set_mwi returned %d\n", retval);	if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0)		if (pci_set_dma_mask(phba->pcidev, DMA_32BIT_MASK) != 0)			goto out_idr_remove;	/*	 * Get the bus address of Bar0 and Bar2 and the number of bytes	 * required by each mapping.	 */	phba->pci_bar0_map = pci_resource_start(phba->pcidev, 0);	bar0map_len        = pci_resource_len(phba->pcidev, 0);	phba->pci_bar2_map = pci_resource_start(phba->pcidev, 2);	bar2map_len        = pci_resource_len(phba->pcidev, 2);	/* Map HBA SLIM and Control Registers to a kernel virtual address. */	phba->slim_memmap_p      = ioremap(phba->pci_bar0_map, bar0map_len);	phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len);	/* Allocate memory for SLI-2 structures */	phba->slim2p = dma_alloc_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,					  &phba->slim2p_mapping, GFP_KERNEL);	if (!phba->slim2p)		goto out_iounmap;	memset(phba->slim2p, 0, SLI2_SLIM_SIZE);	/* Initialize the SLI Layer to run with lpfc HBAs. */	lpfc_sli_setup(phba);	lpfc_sli_queue_setup(phba);	error = lpfc_mem_alloc(phba);	if (error)		goto out_free_slim;	/* Initialize and populate the iocb list per host.  */	INIT_LIST_HEAD(&phba->lpfc_iocb_list);	for (i = 0; i < LPFC_IOCB_LIST_CNT; i++) {		iocbq_entry = kmalloc(sizeof(struct lpfc_iocbq), GFP_KERNEL);		if (iocbq_entry == NULL) {			printk(KERN_ERR "%s: only allocated %d iocbs of "				"expected %d count. Unloading driver.\n",				__FUNCTION__, i, LPFC_IOCB_LIST_CNT);			error = -ENOMEM;			goto out_free_iocbq;		}		memset(iocbq_entry, 0, sizeof(struct lpfc_iocbq));		iotag = lpfc_sli_next_iotag(phba, iocbq_entry);		if (iotag == 0) {			kfree (iocbq_entry);			printk(KERN_ERR "%s: failed to allocate IOTAG. "			       "Unloading driver.\n",				__FUNCTION__);			error = -ENOMEM;			goto out_free_iocbq;		}		spin_lock_irq(phba->host->host_lock);		list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);		phba->total_iocbq_bufs++;		spin_unlock_irq(phba->host->host_lock);	}	/* Initialize HBA structure */	phba->fc_edtov = FF_DEF_EDTOV;	phba->fc_ratov = FF_DEF_RATOV;	phba->fc_altov = FF_DEF_ALTOV;	phba->fc_arbtov = FF_DEF_ARBTOV;	INIT_LIST_HEAD(&phba->work_list);	phba->work_ha_mask = (HA_ERATT|HA_MBATT|HA_LATT);	phba->work_ha_mask |= (HA_RXMASK << (LPFC_ELS_RING * 4));	/* Startup the kernel thread for this host adapter. */	phba->worker_thread = kthread_run(lpfc_do_work, phba,				       "lpfc_worker_%d", phba->brd_no);	if (IS_ERR(phba->worker_thread)) {		error = PTR_ERR(phba->worker_thread);		goto out_free_iocbq;	}	/* We can rely on a queue depth attribute only after SLI HBA setup */	host->can_queue = phba->cfg_hba_queue_depth - 10;	/* Tell the midlayer we support 16 byte commands */	host->max_cmd_len = 16;	/* Initialize the list of scsi buffers used by driver for scsi IO. */	INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);	host->transportt = lpfc_transport_template;	host->hostdata[0] = (unsigned long)phba;	pci_set_drvdata(pdev, host);	error = scsi_add_host(host, &pdev->dev);	if (error)		goto out_kthread_stop;	error = lpfc_alloc_sysfs_attr(phba);	if (error)		goto out_kthread_stop;	error =	request_irq(phba->pcidev->irq, lpfc_intr_handler, SA_SHIRQ,							LPFC_DRIVER_NAME, phba);	if (error) {		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,			"%d:0451 Enable interrupt handler failed\n",			phba->brd_no);		goto out_free_sysfs_attr;	}	phba->MBslimaddr = phba->slim_memmap_p;	phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;	phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;	phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;	phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;	error = lpfc_sli_hba_setup(phba);	if (error)		goto out_free_irq;	/*	 * set fixed host attributes	 * Must done after lpfc_sli_hba_setup()	 */	fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn);	fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn);	fc_host_supported_classes(host) = FC_COS_CLASS3;	memset(fc_host_supported_fc4s(host), 0,		sizeof(fc_host_supported_fc4s(host)));	fc_host_supported_fc4s(host)[2] = 1;	fc_host_supported_fc4s(host)[7] = 1;	lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host));	fc_host_supported_speeds(host) = 0;	switch (FC_JEDEC_ID(phba->vpd.rev.biuRev)) {	case VIPER_JEDEC_ID:		fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT;		break;	case HELIOS_JEDEC_ID:		fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT;		/* Fall through */	case CENTAUR_2G_JEDEC_ID:	case PEGASUS_JEDEC_ID:	case THOR_JEDEC_ID:		fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT;		/* Fall through */	default:		fc_host_supported_speeds(host) = FC_PORTSPEED_1GBIT;	}	fc_host_maxframe_size(host) =		((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |		 (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);	/* This value is also unchanging */	memset(fc_host_active_fc4s(host), 0,		sizeof(fc_host_active_fc4s(host)));	fc_host_active_fc4s(host)[2] = 1;	fc_host_active_fc4s(host)[7] = 1;	spin_lock_irq(phba->host->host_lock);	phba->fc_flag &= ~FC_LOADING;	spin_unlock_irq(phba->host->host_lock);	return 0;out_free_irq:	lpfc_stop_timer(phba);	phba->work_hba_events = 0;	free_irq(phba->pcidev->irq, phba);out_free_sysfs_attr:	lpfc_free_sysfs_attr(phba);out_kthread_stop:	kthread_stop(phba->worker_thread);out_free_iocbq:	list_for_each_entry_safe(iocbq_entry, iocbq_next,						&phba->lpfc_iocb_list, list) {		spin_lock_irq(phba->host->host_lock);		kfree(iocbq_entry);		phba->total_iocbq_bufs--;		spin_unlock_irq(phba->host->host_lock);	}	lpfc_mem_free(phba);out_free_slim:	dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,							phba->slim2p_mapping);out_iounmap:	iounmap(phba->ctrl_regs_memmap_p);	iounmap(phba->slim_memmap_p);out_idr_remove:	idr_remove(&lpfc_hba_index, phba->brd_no);out_put_host:	scsi_host_put(host);out_release_regions:	pci_release_regions(pdev);out_disable_device:	pci_disable_device(pdev);out:	return error;}static void __devexitlpfc_pci_remove_one(struct pci_dev *pdev){	struct Scsi_Host   *host = pci_get_drvdata(pdev);	struct lpfc_hba    *phba = (struct lpfc_hba *)host->hostdata[0];	unsigned long iflag;	lpfc_free_sysfs_attr(phba);	spin_lock_irqsave(phba->host->host_lock, iflag);	phba->fc_flag |= FC_UNLOADING;	spin_unlock_irqrestore(phba->host->host_lock, iflag);	fc_remove_host(phba->host);	scsi_remove_host(phba->host);	kthread_stop(phba->worker_thread);	/*	 * Bring down the SLI Layer. This step disable all interrupts,	 * clears the rings, discards all mailbox commands, and resets	 * the HBA.	 */	lpfc_sli_hba_down(phba);	/* Release the irq reservation */	free_irq(phba->pcidev->irq, phba);	lpfc_cleanup(phba, 0);	lpfc_stop_timer(phba);	phba->work_hba_events = 0;	/*	 * Call scsi_free before mem_free since scsi bufs are released to their	 * corresponding pools here.	 */	lpfc_scsi_free(phba);	lpfc_mem_free(phba);	/* Free resources associated with SLI2 interface */	dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,			  phba->slim2p, phba->slim2p_mapping);	/* unmap adapter SLIM and Control Registers */	iounmap(phba->ctrl_regs_memmap_p);	iounmap(phba->slim_memmap_p);	pci_release_regions(phba->pcidev);	pci_disable_device(phba->pcidev);	idr_remove(&lpfc_hba_index, phba->brd_no);	scsi_host_put(phba->host);	pci_set_drvdata(pdev, NULL);}static struct pci_device_id lpfc_id_table[] = {	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FIREFLY,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_CENTAUR,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_DRAGONFLY,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SUPERFLY,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_RFLY,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_TFLY,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP101,		PCI_ANY_ID, PCI_ANY_ID, },	{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,		PCI_ANY_ID, PCI_ANY_ID, },	{ 0 }};MODULE_DEVICE_TABLE(pci, lpfc_id_table);static struct pci_driver lpfc_driver = {	.name		= LPFC_DRIVER_NAME,	.id_table	= lpfc_id_table,	.probe		= lpfc_pci_probe_one,	.remove		= __devexit_p(lpfc_pci_remove_one),};static int __initlpfc_init(void){	int error = 0;	printk(LPFC_MODULE_DESC "\n");	printk(LPFC_COPYRIGHT "\n");	lpfc_transport_template =				fc_attach_transport(&lpfc_transport_functions);	if (!lpfc_transport_template)		return -ENOMEM;	error = pci_register_driver(&lpfc_driver);	if (error)		fc_release_transport(lpfc_transport_template);	return error;}static void __exitlpfc_exit(void){	pci_unregister_driver(&lpfc_driver);	fc_release_transport(lpfc_transport_template);}module_init(lpfc_init);module_exit(lpfc_exit);MODULE_LICENSE("GPL");MODULE_DESCRIPTION(LPFC_MODULE_DESC);MODULE_AUTHOR("Emulex Corporation - tech.support@emulex.com");MODULE_VERSION("0:" LPFC_DRIVER_VERSION);

⌨️ 快捷键说明

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