📄 lpfc_init.c
字号:
} 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 + -