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 13:01:40 -0500 |
commit | 6669f9bb902b8c3f5e33cb8c32c8c0eec6ed68ed (patch) | |
tree | e143e916abc71ff3c7edb7a5508d480391efc1ee /drivers/scsi/lpfc/lpfc_init.c | |
parent | 4d9ab994e214d35107017c342aca42477b137316 (diff) |
[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 d654c0e3db4d..a7b5566ea0b5 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) | |||
1669 | oneConnect = 1; | 1669 | oneConnect = 1; |
1670 | m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"}; | 1670 | m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"}; |
1671 | break; | 1671 | break; |
1672 | case PCI_DEVICE_ID_TS_BE3: | ||
1673 | oneConnect = 1; | ||
1674 | m = (typeof(m)) {"OCeXXXXX-F", max_speed, "PCIe"}; | ||
1675 | break; | ||
1672 | default: | 1676 | default: |
1673 | m = (typeof(m)){ NULL }; | 1677 | m = (typeof(m)){ NULL }; |
1674 | break; | 1678 | break; |
@@ -2699,6 +2703,63 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba) | |||
2699 | } | 2703 | } |
2700 | 2704 | ||
2701 | /** | 2705 | /** |
2706 | * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support | ||
2707 | * @phba: pointer to lpfc hba data structure. | ||
2708 | * | ||
2709 | * This function uses the QUERY_FW_CFG mailbox command to determine if the | ||
2710 | * firmware loaded supports FCoE. A return of zero indicates that the mailbox | ||
2711 | * was successful and the firmware supports FCoE. Any other return indicates | ||
2712 | * a error. It is assumed that this function will be called before interrupts | ||
2713 | * are enabled. | ||
2714 | **/ | ||
2715 | static int | ||
2716 | lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba) | ||
2717 | { | ||
2718 | int rc = 0; | ||
2719 | LPFC_MBOXQ_t *mboxq; | ||
2720 | struct lpfc_mbx_query_fw_cfg *query_fw_cfg; | ||
2721 | uint32_t length; | ||
2722 | uint32_t shdr_status, shdr_add_status; | ||
2723 | |||
2724 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
2725 | if (!mboxq) { | ||
2726 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2727 | "2621 Failed to allocate mbox for " | ||
2728 | "query firmware config cmd\n"); | ||
2729 | return -ENOMEM; | ||
2730 | } | ||
2731 | query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg; | ||
2732 | length = (sizeof(struct lpfc_mbx_query_fw_cfg) - | ||
2733 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
2734 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, | ||
2735 | LPFC_MBOX_OPCODE_QUERY_FW_CFG, | ||
2736 | length, LPFC_SLI4_MBX_EMBED); | ||
2737 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | ||
2738 | /* The IOCTL status is embedded in the mailbox subheader. */ | ||
2739 | shdr_status = bf_get(lpfc_mbox_hdr_status, | ||
2740 | &query_fw_cfg->header.cfg_shdr.response); | ||
2741 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | ||
2742 | &query_fw_cfg->header.cfg_shdr.response); | ||
2743 | if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) { | ||
2744 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
2745 | "2622 Query Firmware Config failed " | ||
2746 | "mbx status x%x, status x%x add_status x%x\n", | ||
2747 | rc, shdr_status, shdr_add_status); | ||
2748 | return -EINVAL; | ||
2749 | } | ||
2750 | if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) { | ||
2751 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
2752 | "2623 FCoE Function not supported by firmware. " | ||
2753 | "Function mode = %08x\n", | ||
2754 | query_fw_cfg->function_mode); | ||
2755 | return -EINVAL; | ||
2756 | } | ||
2757 | if (rc != MBX_TIMEOUT) | ||
2758 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
2759 | return 0; | ||
2760 | } | ||
2761 | |||
2762 | /** | ||
2702 | * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code | 2763 | * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code |
2703 | * @phba: pointer to lpfc hba data structure. | 2764 | * @phba: pointer to lpfc hba data structure. |
2704 | * @acqe_link: pointer to the async link completion queue entry. | 2765 | * @acqe_link: pointer to the async link completion queue entry. |
@@ -2918,6 +2979,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
2918 | { | 2979 | { |
2919 | uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); | 2980 | uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); |
2920 | int rc; | 2981 | int rc; |
2982 | struct lpfc_vport *vport; | ||
2983 | struct lpfc_nodelist *ndlp; | ||
2984 | struct Scsi_Host *shost; | ||
2921 | 2985 | ||
2922 | phba->fc_eventTag = acqe_fcoe->event_tag; | 2986 | phba->fc_eventTag = acqe_fcoe->event_tag; |
2923 | phba->fcoe_eventtag = acqe_fcoe->event_tag; | 2987 | phba->fcoe_eventtag = acqe_fcoe->event_tag; |
@@ -2925,7 +2989,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
2925 | case LPFC_FCOE_EVENT_TYPE_NEW_FCF: | 2989 | case LPFC_FCOE_EVENT_TYPE_NEW_FCF: |
2926 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 2990 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
2927 | "2546 New FCF found index 0x%x tag 0x%x\n", | 2991 | "2546 New FCF found index 0x%x tag 0x%x\n", |
2928 | acqe_fcoe->fcf_index, | 2992 | acqe_fcoe->index, |
2929 | acqe_fcoe->event_tag); | 2993 | acqe_fcoe->event_tag); |
2930 | /* | 2994 | /* |
2931 | * If the current FCF is in discovered state, or | 2995 | * If the current FCF is in discovered state, or |
@@ -2958,10 +3022,10 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
2958 | case LPFC_FCOE_EVENT_TYPE_FCF_DEAD: | 3022 | case LPFC_FCOE_EVENT_TYPE_FCF_DEAD: |
2959 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 3023 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
2960 | "2549 FCF disconnected fron network index 0x%x" | 3024 | "2549 FCF disconnected fron network index 0x%x" |
2961 | " tag 0x%x\n", acqe_fcoe->fcf_index, | 3025 | " tag 0x%x\n", acqe_fcoe->index, |
2962 | acqe_fcoe->event_tag); | 3026 | acqe_fcoe->event_tag); |
2963 | /* If the event is not for currently used fcf do nothing */ | 3027 | /* If the event is not for currently used fcf do nothing */ |
2964 | if (phba->fcf.fcf_indx != acqe_fcoe->fcf_index) | 3028 | if (phba->fcf.fcf_indx != acqe_fcoe->index) |
2965 | break; | 3029 | break; |
2966 | /* | 3030 | /* |
2967 | * Currently, driver support only one FCF - so treat this as | 3031 | * Currently, driver support only one FCF - so treat this as |
@@ -2971,7 +3035,28 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
2971 | /* Unregister FCF if no devices connected to it */ | 3035 | /* Unregister FCF if no devices connected to it */ |
2972 | lpfc_unregister_unused_fcf(phba); | 3036 | lpfc_unregister_unused_fcf(phba); |
2973 | break; | 3037 | break; |
2974 | 3038 | case LPFC_FCOE_EVENT_TYPE_CVL: | |
3039 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | ||
3040 | "2718 Clear Virtual Link Received for VPI 0x%x" | ||
3041 | " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); | ||
3042 | vport = lpfc_find_vport_by_vpid(phba, | ||
3043 | acqe_fcoe->index /*- phba->vpi_base*/); | ||
3044 | if (!vport) | ||
3045 | break; | ||
3046 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | ||
3047 | if (!ndlp) | ||
3048 | break; | ||
3049 | shost = lpfc_shost_from_vport(vport); | ||
3050 | lpfc_linkdown_port(vport); | ||
3051 | if (vport->port_type != LPFC_NPIV_PORT) { | ||
3052 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | ||
3053 | spin_lock_irq(shost->host_lock); | ||
3054 | ndlp->nlp_flag |= NLP_DELAY_TMO; | ||
3055 | spin_unlock_irq(shost->host_lock); | ||
3056 | ndlp->nlp_last_elscmd = ELS_CMD_FLOGI; | ||
3057 | vport->port_state = LPFC_FLOGI; | ||
3058 | } | ||
3059 | break; | ||
2975 | default: | 3060 | default: |
2976 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 3061 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
2977 | "0288 Unknown FCoE event type 0x%x event tag " | 3062 | "0288 Unknown FCoE event type 0x%x event tag " |
@@ -3463,6 +3548,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
3463 | if (unlikely(rc)) | 3548 | if (unlikely(rc)) |
3464 | goto out_free_bsmbx; | 3549 | goto out_free_bsmbx; |
3465 | 3550 | ||
3551 | rc = lpfc_sli4_fw_cfg_check(phba); | ||
3552 | if (unlikely(rc)) | ||
3553 | goto out_free_bsmbx; | ||
3554 | |||
3466 | /* Set up the hba's configuration parameters. */ | 3555 | /* Set up the hba's configuration parameters. */ |
3467 | rc = lpfc_sli4_read_config(phba); | 3556 | rc = lpfc_sli4_read_config(phba); |
3468 | if (unlikely(rc)) | 3557 | if (unlikely(rc)) |
@@ -6687,6 +6776,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
6687 | { | 6776 | { |
6688 | struct lpfc_hba *phba; | 6777 | struct lpfc_hba *phba; |
6689 | struct lpfc_vport *vport = NULL; | 6778 | struct lpfc_vport *vport = NULL; |
6779 | struct Scsi_Host *shost = NULL; | ||
6690 | int error; | 6780 | int error; |
6691 | uint32_t cfg_mode, intr_mode; | 6781 | uint32_t cfg_mode, intr_mode; |
6692 | 6782 | ||
@@ -6765,6 +6855,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
6765 | goto out_destroy_shost; | 6855 | goto out_destroy_shost; |
6766 | } | 6856 | } |
6767 | 6857 | ||
6858 | shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */ | ||
6768 | /* Now, trying to enable interrupt and bring up the device */ | 6859 | /* Now, trying to enable interrupt and bring up the device */ |
6769 | cfg_mode = phba->cfg_use_msi; | 6860 | cfg_mode = phba->cfg_use_msi; |
6770 | while (true) { | 6861 | while (true) { |
@@ -6831,6 +6922,8 @@ out_unset_pci_mem_s3: | |||
6831 | lpfc_sli_pci_mem_unset(phba); | 6922 | lpfc_sli_pci_mem_unset(phba); |
6832 | out_disable_pci_dev: | 6923 | out_disable_pci_dev: |
6833 | lpfc_disable_pci_dev(phba); | 6924 | lpfc_disable_pci_dev(phba); |
6925 | if (shost) | ||
6926 | scsi_host_put(shost); | ||
6834 | out_free_phba: | 6927 | out_free_phba: |
6835 | lpfc_hba_free(phba); | 6928 | lpfc_hba_free(phba); |
6836 | return error; | 6929 | return error; |
@@ -7214,6 +7307,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
7214 | { | 7307 | { |
7215 | struct lpfc_hba *phba; | 7308 | struct lpfc_hba *phba; |
7216 | struct lpfc_vport *vport = NULL; | 7309 | struct lpfc_vport *vport = NULL; |
7310 | struct Scsi_Host *shost = NULL; | ||
7217 | int error; | 7311 | int error; |
7218 | uint32_t cfg_mode, intr_mode; | 7312 | uint32_t cfg_mode, intr_mode; |
7219 | int mcnt; | 7313 | int mcnt; |
@@ -7294,6 +7388,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
7294 | goto out_destroy_shost; | 7388 | goto out_destroy_shost; |
7295 | } | 7389 | } |
7296 | 7390 | ||
7391 | shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */ | ||
7297 | /* Now, trying to enable interrupt and bring up the device */ | 7392 | /* Now, trying to enable interrupt and bring up the device */ |
7298 | cfg_mode = phba->cfg_use_msi; | 7393 | cfg_mode = phba->cfg_use_msi; |
7299 | while (true) { | 7394 | while (true) { |
@@ -7362,6 +7457,8 @@ out_unset_pci_mem_s4: | |||
7362 | lpfc_sli4_pci_mem_unset(phba); | 7457 | lpfc_sli4_pci_mem_unset(phba); |
7363 | out_disable_pci_dev: | 7458 | out_disable_pci_dev: |
7364 | lpfc_disable_pci_dev(phba); | 7459 | lpfc_disable_pci_dev(phba); |
7460 | if (shost) | ||
7461 | scsi_host_put(shost); | ||
7365 | out_free_phba: | 7462 | out_free_phba: |
7366 | lpfc_hba_free(phba); | 7463 | lpfc_hba_free(phba); |
7367 | return error; | 7464 | return error; |
@@ -7936,6 +8033,8 @@ static struct pci_device_id lpfc_id_table[] = { | |||
7936 | PCI_ANY_ID, PCI_ANY_ID, }, | 8033 | PCI_ANY_ID, PCI_ANY_ID, }, |
7937 | {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK, | 8034 | {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK, |
7938 | PCI_ANY_ID, PCI_ANY_ID, }, | 8035 | PCI_ANY_ID, PCI_ANY_ID, }, |
8036 | {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TS_BE3, | ||
8037 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
7939 | { 0 } | 8038 | { 0 } |
7940 | }; | 8039 | }; |
7941 | 8040 | ||