diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-10-02 15:16:45 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 12:01:40 -0600 |
commit | 6669f9bb902b8c3f5e33cb8c32c8c0eec6ed68ed (patch) | |
tree | e143e916abc71ff3c7edb7a5508d480391efc1ee /drivers/scsi/lpfc/lpfc_init.c | |
parent | 4d9ab994e214d35107017c342aca42477b137316 (diff) | |
download | linux-3.10-6669f9bb902b8c3f5e33cb8c32c8c0eec6ed68ed.tar.gz linux-3.10-6669f9bb902b8c3f5e33cb8c32c8c0eec6ed68ed.tar.bz2 linux-3.10-6669f9bb902b8c3f5e33cb8c32c8c0eec6ed68ed.zip |
[SCSI] lpfc 8.3.5: fix VPI registration, error clean up and add support for vlink events
This patch includes the following fixes and new features:
- Fix mask size for CT field in WQE
- Fix VPI base not used when unregistering VPI on port 1.
- Fix UNREG_VPI mailbox command to unreg the correct VPI
- Fixed Check for aborted els command
- Fix error when trying to load driver with wrong firmware on FCoE HBA.
- Fix bug with probe_one routines not putting the Scsi_Host back upon error
- Add support for Clear Virtual Link Async Events
- Add support for unsolicited CT exchange sequence abort
- Add 0x0714 OCeXXXXX PCI ID
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 107 |
1 files changed, 103 insertions, 4 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index d654c0e3db4..a7b5566ea0b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1669,6 +1669,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) oneConnect = 1; m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"}; break; + case PCI_DEVICE_ID_TS_BE3: + oneConnect = 1; + m = (typeof(m)) {"OCeXXXXX-F", max_speed, "PCIe"}; + break; default: m = (typeof(m)){ NULL }; break; @@ -2699,6 +2703,63 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba) } /** + * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support + * @phba: pointer to lpfc hba data structure. + * + * This function uses the QUERY_FW_CFG mailbox command to determine if the + * firmware loaded supports FCoE. A return of zero indicates that the mailbox + * was successful and the firmware supports FCoE. Any other return indicates + * a error. It is assumed that this function will be called before interrupts + * are enabled. + **/ +static int +lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba) +{ + int rc = 0; + LPFC_MBOXQ_t *mboxq; + struct lpfc_mbx_query_fw_cfg *query_fw_cfg; + uint32_t length; + uint32_t shdr_status, shdr_add_status; + + mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2621 Failed to allocate mbox for " + "query firmware config cmd\n"); + return -ENOMEM; + } + query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg; + length = (sizeof(struct lpfc_mbx_query_fw_cfg) - + sizeof(struct lpfc_sli4_cfg_mhdr)); + lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, + LPFC_MBOX_OPCODE_QUERY_FW_CFG, + length, LPFC_SLI4_MBX_EMBED); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + /* The IOCTL status is embedded in the mailbox subheader. */ + shdr_status = bf_get(lpfc_mbox_hdr_status, + &query_fw_cfg->header.cfg_shdr.response); + shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, + &query_fw_cfg->header.cfg_shdr.response); + if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2622 Query Firmware Config failed " + "mbx status x%x, status x%x add_status x%x\n", + rc, shdr_status, shdr_add_status); + return -EINVAL; + } + if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2623 FCoE Function not supported by firmware. " + "Function mode = %08x\n", + query_fw_cfg->function_mode); + return -EINVAL; + } + if (rc != MBX_TIMEOUT) + mempool_free(mboxq, phba->mbox_mem_pool); + return 0; +} + +/** * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code * @phba: pointer to lpfc hba data structure. * @acqe_link: pointer to the async link completion queue entry. @@ -2918,6 +2979,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, { uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); int rc; + struct lpfc_vport *vport; + struct lpfc_nodelist *ndlp; + struct Scsi_Host *shost; phba->fc_eventTag = acqe_fcoe->event_tag; phba->fcoe_eventtag = acqe_fcoe->event_tag; @@ -2925,7 +2989,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, case LPFC_FCOE_EVENT_TYPE_NEW_FCF: lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "2546 New FCF found index 0x%x tag 0x%x\n", - acqe_fcoe->fcf_index, + acqe_fcoe->index, acqe_fcoe->event_tag); /* * If the current FCF is in discovered state, or @@ -2958,10 +3022,10 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, case LPFC_FCOE_EVENT_TYPE_FCF_DEAD: lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, "2549 FCF disconnected fron network index 0x%x" - " tag 0x%x\n", acqe_fcoe->fcf_index, + " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); /* If the event is not for currently used fcf do nothing */ - if (phba->fcf.fcf_indx != acqe_fcoe->fcf_index) + if (phba->fcf.fcf_indx != acqe_fcoe->index) break; /* * Currently, driver support only one FCF - so treat this as @@ -2971,7 +3035,28 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, /* Unregister FCF if no devices connected to it */ lpfc_unregister_unused_fcf(phba); break; - + case LPFC_FCOE_EVENT_TYPE_CVL: + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "2718 Clear Virtual Link Received for VPI 0x%x" + " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); + vport = lpfc_find_vport_by_vpid(phba, + acqe_fcoe->index /*- phba->vpi_base*/); + if (!vport) + break; + ndlp = lpfc_findnode_did(vport, Fabric_DID); + if (!ndlp) + break; + shost = lpfc_shost_from_vport(vport); + lpfc_linkdown_port(vport); + if (vport->port_type != LPFC_NPIV_PORT) { + mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag |= NLP_DELAY_TMO; + spin_unlock_irq(shost->host_lock); + ndlp->nlp_last_elscmd = ELS_CMD_FLOGI; + vport->port_state = LPFC_FLOGI; + } + break; default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0288 Unknown FCoE event type 0x%x event tag " @@ -3463,6 +3548,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) if (unlikely(rc)) goto out_free_bsmbx; + rc = lpfc_sli4_fw_cfg_check(phba); + if (unlikely(rc)) + goto out_free_bsmbx; + /* Set up the hba's configuration parameters. */ rc = lpfc_sli4_read_config(phba); if (unlikely(rc)) @@ -6687,6 +6776,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) { struct lpfc_hba *phba; struct lpfc_vport *vport = NULL; + struct Scsi_Host *shost = NULL; int error; uint32_t cfg_mode, intr_mode; @@ -6765,6 +6855,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_destroy_shost; } + shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */ /* Now, trying to enable interrupt and bring up the device */ cfg_mode = phba->cfg_use_msi; while (true) { @@ -6831,6 +6922,8 @@ out_unset_pci_mem_s3: lpfc_sli_pci_mem_unset(phba); out_disable_pci_dev: lpfc_disable_pci_dev(phba); + if (shost) + scsi_host_put(shost); out_free_phba: lpfc_hba_free(phba); return error; @@ -7214,6 +7307,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) { struct lpfc_hba *phba; struct lpfc_vport *vport = NULL; + struct Scsi_Host *shost = NULL; int error; uint32_t cfg_mode, intr_mode; int mcnt; @@ -7294,6 +7388,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_destroy_shost; } + shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */ /* Now, trying to enable interrupt and bring up the device */ cfg_mode = phba->cfg_use_msi; while (true) { @@ -7362,6 +7457,8 @@ out_unset_pci_mem_s4: lpfc_sli4_pci_mem_unset(phba); out_disable_pci_dev: lpfc_disable_pci_dev(phba); + if (shost) + scsi_host_put(shost); out_free_phba: lpfc_hba_free(phba); return error; @@ -7936,6 +8033,8 @@ static struct pci_device_id lpfc_id_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK, PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TS_BE3, + PCI_ANY_ID, PCI_ANY_ID, }, { 0 } }; |