X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Flpfc%2Flpfc_init.c;h=391ca50293f2a5a6dca187291d86e867ea8e418c;hb=41415862a23f422b80eccc92cf885935139e2415;hp=c90723860a049e15232452b60921909645c81bde;hpb=eedb9f09e92598c165de37a8c210434d270ca3a6;p=linux-2.6-omap-h63xx.git diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index c90723860a0..391ca50293f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2006 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -126,34 +126,26 @@ lpfc_config_port_prep(struct lpfc_hba * phba) return -ERESTART; } - /* The HBA's current state is provided by the ProgType and rr fields. - * Read and check the value of these fields before continuing to config - * this port. + /* + * The value of rr must be 1 since the driver set the cv field to 1. + * This setting requires the FW to set all revision fields. */ - if (mb->un.varRdRev.rr == 0 || mb->un.varRdRev.un.b.ProgType != 2) { - /* Old firmware */ + if (mb->un.varRdRev.rr == 0) { vp->rev.rBit = 0; - lpfc_printf_log(phba, - KERN_ERR, - LOG_INIT, - "%d:0440 Adapter failed to init, mbxCmd x%x " - "READ_REV detected outdated firmware" - "Data: x%x\n", - phba->brd_no, - mb->mbxCommand, 0); + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "%d:0440 Adapter failed to init, READ_REV has " + "missing revision information.\n", + phba->brd_no); mempool_free(pmb, phba->mbox_mem_pool); return -ERESTART; - } else { - vp->rev.rBit = 1; - vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev; - memcpy(vp->rev.sli1FwName, - (char*)mb->un.varRdRev.sli1FwName, 16); - vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev; - memcpy(vp->rev.sli2FwName, - (char *)mb->un.varRdRev.sli2FwName, 16); } /* Save information as VPD data */ + vp->rev.rBit = 1; + vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev; + memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16); + vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev; + memcpy(vp->rev.sli2FwName, (char *) mb->un.varRdRev.sli2FwName, 16); vp->rev.biuRev = mb->un.varRdRev.biuRev; vp->rev.smRev = mb->un.varRdRev.smRev; vp->rev.smFwRev = mb->un.varRdRev.un.smFwRev; @@ -378,6 +370,10 @@ lpfc_config_port_post(struct lpfc_hba * phba) if (psli->num_rings > 3) status |= HC_R3INT_ENA; + if ((phba->cfg_poll & ENABLE_FCP_RING_POLLING) && + (phba->cfg_poll & DISABLE_FCP_RING_INT)) + status &= ~(HC_R0INT_ENA << LPFC_FCP_RING); + writel(status, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ spin_unlock_irq(phba->host->host_lock); @@ -463,9 +459,45 @@ lpfc_hba_down_prep(struct lpfc_hba * phba) lpfc_els_flush_cmd(phba); lpfc_disc_flush_list(phba); + /* Disable SLI2 since we disabled interrupts */ + phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; return (0); } +/************************************************************************/ +/* */ +/* lpfc_hba_down_post */ +/* This routine will do uninitialization after the HBA is reset */ +/* when bringing down the SLI Layer. */ +/* This routine returns 0 on success. Any other return value */ +/* indicates an error. */ +/* */ +/************************************************************************/ +int +lpfc_hba_down_post(struct lpfc_hba * phba) +{ + struct lpfc_sli *psli = &phba->sli; + struct lpfc_sli_ring *pring; + struct lpfc_dmabuf *mp, *next_mp; + int i; + + /* Cleanup preposted buffers on the ELS ring */ + pring = &psli->ring[LPFC_ELS_RING]; + list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { + list_del(&mp->list); + pring->postbufq_cnt--; + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + + for (i = 0; i < psli->num_rings; i++) { + pring = &psli->ring[i]; + lpfc_sli_abort_iocb_ring(phba, pring); + } + + return 0; +} + /************************************************************************/ /* */ /* lpfc_handle_eratt */ @@ -480,20 +512,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; - /* - * If a reset is sent to the HBA restore PCI configuration registers. - */ - if ( phba->hba_state == LPFC_INIT_START ) { - mdelay(1); - readl(phba->HCregaddr); /* flush */ - writel(0, phba->HCregaddr); - readl(phba->HCregaddr); /* flush */ - - /* Restore PCI cmd register */ - pci_write_config_word(phba->pcidev, - PCI_COMMAND, phba->pci_cfg_value); - } - if (phba->work_hs & HS_FFER6) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, @@ -520,6 +538,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba) * attempt to restart it. */ lpfc_offline(phba); + lpfc_sli_brdrestart(phba); if (lpfc_online(phba) == 0) { /* Initialize the HBA */ mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); return; @@ -536,7 +555,8 @@ lpfc_handle_eratt(struct lpfc_hba * phba) phba->work_status[0], phba->work_status[1]); lpfc_offline(phba); - + phba->hba_state = LPFC_HBA_ERROR; + lpfc_hba_down_post(phba); } } @@ -571,6 +591,8 @@ lpfc_handle_latt(struct lpfc_hba * phba) rc = -EIO; + /* Cleanup any outstanding ELS commands */ + lpfc_els_flush_cmd(phba); psli->slistat.link_event++; lpfc_read_la(phba, pmb, mp); @@ -765,96 +787,139 @@ static void lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) { lpfc_vpd_t *vp; - uint32_t id; - uint8_t hdrtype; - char str[16]; + uint16_t dev_id = phba->pcidev->device; + uint16_t dev_subid = phba->pcidev->subsystem_device; + uint8_t hdrtype = phba->pcidev->hdr_type; + char *model_str = ""; vp = &phba->vpd; - pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id); - pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); - switch ((id >> 16) & 0xffff) { + switch (dev_id) { case PCI_DEVICE_ID_FIREFLY: - strcpy(str, "LP6000 1"); + model_str = "LP6000 1Gb PCI"; break; case PCI_DEVICE_ID_SUPERFLY: if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) - strcpy(str, "LP7000 1"); + model_str = "LP7000 1Gb PCI"; else - strcpy(str, "LP7000E 1"); + model_str = "LP7000E 1Gb PCI"; break; case PCI_DEVICE_ID_DRAGONFLY: - strcpy(str, "LP8000 1"); + model_str = "LP8000 1Gb PCI"; break; case PCI_DEVICE_ID_CENTAUR: if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) - strcpy(str, "LP9002 2"); + model_str = "LP9002 2Gb PCI"; else - strcpy(str, "LP9000 1"); + model_str = "LP9000 1Gb PCI"; break; case PCI_DEVICE_ID_RFLY: - strcpy(str, "LP952 2"); + model_str = "LP952 2Gb PCI"; break; case PCI_DEVICE_ID_PEGASUS: - strcpy(str, "LP9802 2"); + model_str = "LP9802 2Gb PCI-X"; break; case PCI_DEVICE_ID_THOR: if (hdrtype == 0x80) - strcpy(str, "LP10000DC 2"); + model_str = "LP10000DC 2Gb 2-port PCI-X"; else - strcpy(str, "LP10000 2"); + model_str = "LP10000 2Gb PCI-X"; break; case PCI_DEVICE_ID_VIPER: - strcpy(str, "LPX1000 10"); + model_str = "LPX1000 10Gb PCI-X"; break; case PCI_DEVICE_ID_PFLY: - strcpy(str, "LP982 2"); + model_str = "LP982 2Gb PCI-X"; break; case PCI_DEVICE_ID_TFLY: if (hdrtype == 0x80) - strcpy(str, "LP1050DC 2"); + model_str = "LP1050DC 2Gb 2-port PCI-X"; else - strcpy(str, "LP1050 2"); + model_str = "LP1050 2Gb PCI-X"; break; case PCI_DEVICE_ID_HELIOS: if (hdrtype == 0x80) - strcpy(str, "LP11002 4"); + model_str = "LP11002 4Gb 2-port PCI-X2"; + else + model_str = "LP11000 4Gb PCI-X2"; + break; + case PCI_DEVICE_ID_HELIOS_SCSP: + model_str = "LP11000-SP 4Gb PCI-X2"; + break; + case PCI_DEVICE_ID_HELIOS_DCSP: + model_str = "LP11002-SP 4Gb 2-port PCI-X2"; + break; + case PCI_DEVICE_ID_NEPTUNE: + if (hdrtype == 0x80) + model_str = "LPe1002 4Gb 2-port"; else - strcpy(str, "LP11000 4"); + model_str = "LPe1000 4Gb PCIe"; + break; + case PCI_DEVICE_ID_NEPTUNE_SCSP: + model_str = "LPe1000-SP 4Gb PCIe"; + break; + case PCI_DEVICE_ID_NEPTUNE_DCSP: + model_str = "LPe1002-SP 4Gb 2-port PCIe"; break; case PCI_DEVICE_ID_BMID: - strcpy(str, "LP1150 4"); + model_str = "LP1150 4Gb PCI-X2"; break; case PCI_DEVICE_ID_BSMB: - strcpy(str, "LP111 4"); + model_str = "LP111 4Gb PCI-X2"; break; case PCI_DEVICE_ID_ZEPHYR: if (hdrtype == 0x80) - strcpy(str, "LPe11002 4"); + model_str = "LPe11002 4Gb 2-port PCIe"; else - strcpy(str, "LPe11000 4"); + model_str = "LPe11000 4Gb PCIe"; + break; + case PCI_DEVICE_ID_ZEPHYR_SCSP: + model_str = "LPe11000-SP 4Gb PCIe"; + break; + case PCI_DEVICE_ID_ZEPHYR_DCSP: + model_str = "LPe11002-SP 4Gb 2-port PCIe"; break; case PCI_DEVICE_ID_ZMID: - strcpy(str, "LPe1150 4"); + model_str = "LPe1150 4Gb PCIe"; break; case PCI_DEVICE_ID_ZSMB: - strcpy(str, "LPe111 4"); + model_str = "LPe111 4Gb PCIe"; break; case PCI_DEVICE_ID_LP101: - strcpy(str, "LP101 2"); + model_str = "LP101 2Gb PCI-X"; break; case PCI_DEVICE_ID_LP10000S: - strcpy(str, "LP10000-S 2"); + model_str = "LP10000-S 2Gb PCI"; + break; + case PCI_DEVICE_ID_LP11000S: + case PCI_DEVICE_ID_LPE11000S: + switch (dev_subid) { + case PCI_SUBSYSTEM_ID_LP11000S: + model_str = "LP11002-S 4Gb PCI-X2"; + break; + case PCI_SUBSYSTEM_ID_LP11002S: + model_str = "LP11000-S 4Gb 2-port PCI-X2"; + break; + case PCI_SUBSYSTEM_ID_LPE11000S: + model_str = "LPe11002-S 4Gb PCIe"; + break; + case PCI_SUBSYSTEM_ID_LPE11002S: + model_str = "LPe11002-S 4Gb 2-port PCIe"; + break; + case PCI_SUBSYSTEM_ID_LPE11010S: + model_str = "LPe11010-S 4Gb 10-port PCIe"; + break; + default: + break; + } break; default: - memset(str, 0, 16); break; } if (mdp) - sscanf(str, "%s", mdp); + sscanf(model_str, "%s", mdp); if (descp) - sprintf(descp, "Emulex LightPulse %s Gigabit PCI Fibre " - "Channel Adapter", str); + sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str); } /**************************************************/ @@ -1196,6 +1261,7 @@ lpfc_stop_timer(struct lpfc_hba * phba) } } + del_timer_sync(&phba->fcp_poll_timer); del_timer_sync(&phba->fc_estabtmo); del_timer_sync(&phba->fc_disctmo); del_timer_sync(&phba->fc_fdmitmo); @@ -1351,7 +1417,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_put_host; host->unique_id = phba->brd_no; - + init_MUTEX(&phba->hba_can_block); INIT_LIST_HEAD(&phba->ctrspbuflist); INIT_LIST_HEAD(&phba->rnidrspbuflist); INIT_LIST_HEAD(&phba->freebufList); @@ -1375,6 +1441,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) psli->mbox_tmo.function = lpfc_mbox_timeout; psli->mbox_tmo.data = (unsigned long)phba; + init_timer(&phba->fcp_poll_timer); + phba->fcp_poll_timer.function = lpfc_poll_timeout; + phba->fcp_poll_timer.data = (unsigned long)phba; + /* * Get all the module params for configuring this host and then * establish the host parameters. @@ -1416,9 +1486,23 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) 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. */ + /* Map HBA SLIM to a kernel virtual address. */ phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len); + if (!phba->slim_memmap_p) { + error = -ENODEV; + dev_printk(KERN_ERR, &pdev->dev, + "ioremap failed for SLIM memory.\n"); + goto out_idr_remove; + } + + /* Map HBA Control Registers to a kernel virtual address. */ phba->ctrl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len); + if (!phba->ctrl_regs_memmap_p) { + error = -ENODEV; + dev_printk(KERN_ERR, &pdev->dev, + "ioremap failed for HBA control registers.\n"); + goto out_iounmap_slim; + } /* Allocate memory for SLI-2 structures */ phba->slim2p = dma_alloc_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE, @@ -1489,10 +1573,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) host->max_cmd_len = 16; /* Initialize the list of scsi buffers used by driver for scsi IO. */ + spin_lock_init(&phba->scsi_buf_list_lock); 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) @@ -1520,6 +1604,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) if (error) goto out_free_irq; + if (phba->cfg_poll & DISABLE_FCP_RING_INT) { + spin_lock_irq(phba->host->host_lock); + lpfc_poll_start_timer(phba); + spin_unlock_irq(phba->host->host_lock); + } + /* * set fixed host attributes * Must done after lpfc_sli_hba_setup() @@ -1590,6 +1680,7 @@ out_free_slim: phba->slim2p_mapping); out_iounmap: iounmap(phba->ctrl_regs_memmap_p); +out_iounmap_slim: iounmap(phba->slim_memmap_p); out_idr_remove: idr_remove(&lpfc_hba_index, phba->brd_no); @@ -1607,7 +1698,7 @@ static void __devexit lpfc_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]; + struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; unsigned long iflag; lpfc_free_sysfs_attr(phba); @@ -1628,6 +1719,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) * the HBA. */ lpfc_sli_hba_down(phba); + lpfc_sli_brdrestart(phba); /* Release the irq reservation */ free_irq(phba->pcidev->irq, phba); @@ -1679,14 +1771,28 @@ static struct pci_device_id lpfc_id_table[] = { 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_NEPTUNE, + PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP, + PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP, + 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_HELIOS_SCSP, + PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP, + 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_ZEPHYR_SCSP, + PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP, + 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, @@ -1697,6 +1803,10 @@ static struct pci_device_id lpfc_id_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S, PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S, + PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S, + PCI_ANY_ID, PCI_ANY_ID, }, { 0 } }; @@ -1704,7 +1814,6 @@ MODULE_DEVICE_TABLE(pci, lpfc_id_table); static struct pci_driver lpfc_driver = { .name = LPFC_DRIVER_NAME, - .owner = THIS_MODULE, .id_table = lpfc_id_table, .probe = lpfc_pci_probe_one, .remove = __devexit_p(lpfc_pci_remove_one),