diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-06-10 17:22:56 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-15 11:09:33 -0400 |
commit | 0c2875893ef27b93d5d3221f8f98ae944d6be5fa (patch) | |
tree | 01e201e3827611c9b5cfc35a5f00b6532fc948ef /drivers | |
parent | f1126688805d77a4798b694439fa48bba6629388 (diff) |
[SCSI] lpfc 8.3.3 : FC/FCOE discovery fixes
Contains the following changes:
- Force vport to send LOGO to fabric controller when deleting vport
- Fixed driver failing to register login when a PLOGI is received
- Fixes for FIP discovery
- Added stricter checks for FCF addressing mode
- Added code to send only FLOGI, FDISC and LOGO to Fabric controller as FIP
- Fixed handling of LOGO from Fabric port
- Fixed consecutive link up events skipped link_down processing
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 13 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 35 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 24 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 2 |
8 files changed, 59 insertions, 26 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 2aabaf9c4053..f72fdf23bf1b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -168,6 +168,19 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
168 | if (elsiocb == NULL) | 168 | if (elsiocb == NULL) |
169 | return NULL; | 169 | return NULL; |
170 | 170 | ||
171 | /* | ||
172 | * If this command is for fabric controller and HBA running | ||
173 | * in FIP mode send FLOGI, FDISC and LOGO as FIP frames. | ||
174 | */ | ||
175 | if ((did == Fabric_DID) && | ||
176 | bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags) && | ||
177 | ((elscmd == ELS_CMD_FLOGI) || | ||
178 | (elscmd == ELS_CMD_FDISC) || | ||
179 | (elscmd == ELS_CMD_LOGO))) | ||
180 | elsiocb->iocb_flag |= LPFC_FIP_ELS; | ||
181 | else | ||
182 | elsiocb->iocb_flag &= ~LPFC_FIP_ELS; | ||
183 | |||
171 | icmd = &elsiocb->iocb; | 184 | icmd = &elsiocb->iocb; |
172 | 185 | ||
173 | /* fill in BDEs for command */ | 186 | /* fill in BDEs for command */ |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 35c41ae75be2..ed46b24a3380 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1197,6 +1197,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1197 | { | 1197 | { |
1198 | struct lpfc_fcf_conn_entry *conn_entry; | 1198 | struct lpfc_fcf_conn_entry *conn_entry; |
1199 | 1199 | ||
1200 | /* If FCF not available return 0 */ | ||
1201 | if (!bf_get(lpfc_fcf_record_fcf_avail, new_fcf_record) || | ||
1202 | !bf_get(lpfc_fcf_record_fcf_valid, new_fcf_record)) | ||
1203 | return 0; | ||
1204 | |||
1200 | if (!phba->cfg_enable_fip) { | 1205 | if (!phba->cfg_enable_fip) { |
1201 | *boot_flag = 0; | 1206 | *boot_flag = 0; |
1202 | *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, | 1207 | *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, |
@@ -1216,6 +1221,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1216 | *boot_flag = 0; | 1221 | *boot_flag = 0; |
1217 | *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, | 1222 | *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, |
1218 | new_fcf_record); | 1223 | new_fcf_record); |
1224 | |||
1225 | /* | ||
1226 | * When there are no FCF connect entries, use driver's default | ||
1227 | * addressing mode - FPMA. | ||
1228 | */ | ||
1229 | if (*addr_mode & LPFC_FCF_FPMA) | ||
1230 | *addr_mode = LPFC_FCF_FPMA; | ||
1231 | |||
1219 | *vlan_id = 0xFFFF; | 1232 | *vlan_id = 0xFFFF; |
1220 | return 1; | 1233 | return 1; |
1221 | } | 1234 | } |
@@ -1241,6 +1254,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1241 | } | 1254 | } |
1242 | 1255 | ||
1243 | /* | 1256 | /* |
1257 | * If connection record does not support any addressing mode, | ||
1258 | * skip the FCF record. | ||
1259 | */ | ||
1260 | if (!(bf_get(lpfc_fcf_record_mac_addr_prov, new_fcf_record) | ||
1261 | & (LPFC_FCF_FPMA | LPFC_FCF_SPMA))) | ||
1262 | continue; | ||
1263 | |||
1264 | /* | ||
1244 | * Check if the connection record specifies a required | 1265 | * Check if the connection record specifies a required |
1245 | * addressing mode. | 1266 | * addressing mode. |
1246 | */ | 1267 | */ |
@@ -1272,6 +1293,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1272 | else | 1293 | else |
1273 | *boot_flag = 0; | 1294 | *boot_flag = 0; |
1274 | 1295 | ||
1296 | /* | ||
1297 | * If user did not specify any addressing mode, or if the | ||
1298 | * prefered addressing mode specified by user is not supported | ||
1299 | * by FCF, allow fabric to pick the addressing mode. | ||
1300 | */ | ||
1275 | *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, | 1301 | *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, |
1276 | new_fcf_record); | 1302 | new_fcf_record); |
1277 | /* | 1303 | /* |
@@ -1297,12 +1323,6 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, | |||
1297 | !(conn_entry->conn_rec.flags & FCFCNCT_AM_SPMA) && | 1323 | !(conn_entry->conn_rec.flags & FCFCNCT_AM_SPMA) && |
1298 | (*addr_mode & LPFC_FCF_FPMA)) | 1324 | (*addr_mode & LPFC_FCF_FPMA)) |
1299 | *addr_mode = LPFC_FCF_FPMA; | 1325 | *addr_mode = LPFC_FCF_FPMA; |
1300 | /* | ||
1301 | * If user did not specify any addressing mode, use FPMA if | ||
1302 | * possible else use SPMA. | ||
1303 | */ | ||
1304 | else if (*addr_mode & LPFC_FCF_FPMA) | ||
1305 | *addr_mode = LPFC_FCF_FPMA; | ||
1306 | 1326 | ||
1307 | if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID) | 1327 | if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID) |
1308 | *vlan_id = conn_entry->conn_rec.vlan_tag; | 1328 | *vlan_id = conn_entry->conn_rec.vlan_tag; |
@@ -1864,7 +1884,7 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1864 | vport->fc_flag &= ~FC_BYPASSED_MODE; | 1884 | vport->fc_flag &= ~FC_BYPASSED_MODE; |
1865 | spin_unlock_irq(shost->host_lock); | 1885 | spin_unlock_irq(shost->host_lock); |
1866 | 1886 | ||
1867 | if (((phba->fc_eventTag + 1) < la->eventTag) || | 1887 | if ((phba->fc_eventTag < la->eventTag) || |
1868 | (phba->fc_eventTag == la->eventTag)) { | 1888 | (phba->fc_eventTag == la->eventTag)) { |
1869 | phba->fc_stat.LinkMultiEvent++; | 1889 | phba->fc_stat.LinkMultiEvent++; |
1870 | if (la->attType == AT_LINK_UP) | 1890 | if (la->attType == AT_LINK_UP) |
@@ -2925,6 +2945,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2925 | lpfc_no_rpi(phba, ndlp); | 2945 | lpfc_no_rpi(phba, ndlp); |
2926 | ndlp->nlp_rpi = 0; | 2946 | ndlp->nlp_rpi = 0; |
2927 | ndlp->nlp_flag &= ~NLP_RPI_VALID; | 2947 | ndlp->nlp_flag &= ~NLP_RPI_VALID; |
2948 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | ||
2928 | return 1; | 2949 | return 1; |
2929 | } | 2950 | } |
2930 | return 0; | 2951 | return 0; |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 749811a1627b..2995d128f07f 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -1128,7 +1128,7 @@ struct fcf_record { | |||
1128 | #define lpfc_fcf_record_mac_5_WORD word4 | 1128 | #define lpfc_fcf_record_mac_5_WORD word4 |
1129 | #define lpfc_fcf_record_fcf_avail_SHIFT 16 | 1129 | #define lpfc_fcf_record_fcf_avail_SHIFT 16 |
1130 | #define lpfc_fcf_record_fcf_avail_MASK 0x000000FF | 1130 | #define lpfc_fcf_record_fcf_avail_MASK 0x000000FF |
1131 | #define lpfc_fcf_record_fc_avail_WORD word4 | 1131 | #define lpfc_fcf_record_fcf_avail_WORD word4 |
1132 | #define lpfc_fcf_record_mac_addr_prov_SHIFT 24 | 1132 | #define lpfc_fcf_record_mac_addr_prov_SHIFT 24 |
1133 | #define lpfc_fcf_record_mac_addr_prov_MASK 0x000000FF | 1133 | #define lpfc_fcf_record_mac_addr_prov_MASK 0x000000FF |
1134 | #define lpfc_fcf_record_mac_addr_prov_WORD word4 | 1134 | #define lpfc_fcf_record_mac_addr_prov_WORD word4 |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index b9b451c09010..bb3dc1dcffe0 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1715,8 +1715,10 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq) | |||
1715 | /* Set up host requested features. */ | 1715 | /* Set up host requested features. */ |
1716 | bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); | 1716 | bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); |
1717 | 1717 | ||
1718 | /* Virtual fabrics and FIPs are not supported yet. */ | 1718 | if (phba->cfg_enable_fip) |
1719 | bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0); | 1719 | bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0); |
1720 | else | ||
1721 | bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 1); | ||
1720 | 1722 | ||
1721 | /* Enable DIF (block guard) only if configured to do so. */ | 1723 | /* Enable DIF (block guard) only if configured to do so. */ |
1722 | if (phba->cfg_enable_bg) | 1724 | if (phba->cfg_enable_bg) |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 09f659f77bb3..3e74136f1ede 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -497,7 +497,7 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
497 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); | 497 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); |
498 | else | 498 | else |
499 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 499 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
500 | if ((ndlp->nlp_type & NLP_FABRIC) && | 500 | if ((ndlp->nlp_DID == Fabric_DID) && |
501 | vport->port_type == LPFC_NPIV_PORT) { | 501 | vport->port_type == LPFC_NPIV_PORT) { |
502 | lpfc_linkdown_port(vport); | 502 | lpfc_linkdown_port(vport); |
503 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 503 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b8cf0a1b1382..ba698d5f31af 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -4491,8 +4491,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
4491 | rc = -ENODEV; | 4491 | rc = -ENODEV; |
4492 | goto out_free_vpd; | 4492 | goto out_free_vpd; |
4493 | } | 4493 | } |
4494 | /* Temporary initialization of lpfc_fip_flag to non-fip */ | 4494 | if (phba->cfg_enable_fip) |
4495 | bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0); | 4495 | bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 1); |
4496 | else | ||
4497 | bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0); | ||
4496 | 4498 | ||
4497 | /* Set up all the queues to the device */ | 4499 | /* Set up all the queues to the device */ |
4498 | rc = lpfc_sli4_queue_setup(phba); | 4500 | rc = lpfc_sli4_queue_setup(phba); |
@@ -5856,18 +5858,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
5856 | 5858 | ||
5857 | fip = bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags); | 5859 | fip = bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags); |
5858 | /* The fcp commands will set command type */ | 5860 | /* The fcp commands will set command type */ |
5859 | if ((!(iocbq->iocb_flag & LPFC_IO_FCP)) && (!fip)) | 5861 | if (iocbq->iocb_flag & LPFC_IO_FCP) |
5860 | command_type = ELS_COMMAND_NON_FIP; | ||
5861 | else if (!(iocbq->iocb_flag & LPFC_IO_FCP)) | ||
5862 | command_type = ELS_COMMAND_FIP; | ||
5863 | else if (iocbq->iocb_flag & LPFC_IO_FCP) | ||
5864 | command_type = FCP_COMMAND; | 5862 | command_type = FCP_COMMAND; |
5865 | else { | 5863 | else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS)) |
5866 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 5864 | command_type = ELS_COMMAND_FIP; |
5867 | "2019 Invalid cmd 0x%x\n", | 5865 | else |
5868 | iocbq->iocb.ulpCommand); | 5866 | command_type = ELS_COMMAND_NON_FIP; |
5869 | return IOCB_ERROR; | 5867 | |
5870 | } | ||
5871 | /* Some of the fields are in the right position already */ | 5868 | /* Some of the fields are in the right position already */ |
5872 | memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); | 5869 | memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); |
5873 | abort_tag = (uint32_t) iocbq->iotag; | 5870 | abort_tag = (uint32_t) iocbq->iotag; |
@@ -11467,6 +11464,7 @@ lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba, | |||
11467 | bf_set(lpfc_fcf_record_fc_map_1, fcf_record, phba->fc_map[1]); | 11464 | bf_set(lpfc_fcf_record_fc_map_1, fcf_record, phba->fc_map[1]); |
11468 | bf_set(lpfc_fcf_record_fc_map_2, fcf_record, phba->fc_map[2]); | 11465 | bf_set(lpfc_fcf_record_fc_map_2, fcf_record, phba->fc_map[2]); |
11469 | bf_set(lpfc_fcf_record_fcf_valid, fcf_record, 1); | 11466 | bf_set(lpfc_fcf_record_fcf_valid, fcf_record, 1); |
11467 | bf_set(lpfc_fcf_record_fcf_avail, fcf_record, 1); | ||
11470 | bf_set(lpfc_fcf_record_fcf_index, fcf_record, fcf_index); | 11468 | bf_set(lpfc_fcf_record_fcf_index, fcf_record, fcf_index); |
11471 | bf_set(lpfc_fcf_record_mac_addr_prov, fcf_record, | 11469 | bf_set(lpfc_fcf_record_mac_addr_prov, fcf_record, |
11472 | LPFC_FCF_FPMA | LPFC_FCF_SPMA); | 11470 | LPFC_FCF_FPMA | LPFC_FCF_SPMA); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 7d37eb7459bf..3c53316cf6d0 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -56,6 +56,7 @@ struct lpfc_iocbq { | |||
56 | #define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */ | 56 | #define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */ |
57 | #define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */ | 57 | #define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */ |
58 | #define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */ | 58 | #define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */ |
59 | #define LPFC_FIP_ELS 0x40 | ||
59 | 60 | ||
60 | uint8_t abort_count; | 61 | uint8_t abort_count; |
61 | uint8_t rsvd2; | 62 | uint8_t rsvd2; |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index a6313ee84ac5..e0b49922193e 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -695,8 +695,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
695 | } | 695 | } |
696 | vport->unreg_vpi_cmpl = VPORT_INVAL; | 696 | vport->unreg_vpi_cmpl = VPORT_INVAL; |
697 | timeout = msecs_to_jiffies(phba->fc_ratov * 2000); | 697 | timeout = msecs_to_jiffies(phba->fc_ratov * 2000); |
698 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
699 | goto skip_logo; | ||
700 | if (!lpfc_issue_els_npiv_logo(vport, ndlp)) | 698 | if (!lpfc_issue_els_npiv_logo(vport, ndlp)) |
701 | while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout) | 699 | while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout) |
702 | timeout = schedule_timeout(timeout); | 700 | timeout = schedule_timeout(timeout); |