Commit 0c287589 authored by James Smart's avatar James Smart Committed by James Bottomley

[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: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent f1126688
...@@ -168,6 +168,19 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, ...@@ -168,6 +168,19 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
if (elsiocb == NULL) if (elsiocb == NULL)
return NULL; return NULL;
/*
* If this command is for fabric controller and HBA running
* in FIP mode send FLOGI, FDISC and LOGO as FIP frames.
*/
if ((did == Fabric_DID) &&
bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags) &&
((elscmd == ELS_CMD_FLOGI) ||
(elscmd == ELS_CMD_FDISC) ||
(elscmd == ELS_CMD_LOGO)))
elsiocb->iocb_flag |= LPFC_FIP_ELS;
else
elsiocb->iocb_flag &= ~LPFC_FIP_ELS;
icmd = &elsiocb->iocb; icmd = &elsiocb->iocb;
/* fill in BDEs for command */ /* fill in BDEs for command */
......
...@@ -1197,6 +1197,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, ...@@ -1197,6 +1197,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
{ {
struct lpfc_fcf_conn_entry *conn_entry; struct lpfc_fcf_conn_entry *conn_entry;
/* If FCF not available return 0 */
if (!bf_get(lpfc_fcf_record_fcf_avail, new_fcf_record) ||
!bf_get(lpfc_fcf_record_fcf_valid, new_fcf_record))
return 0;
if (!phba->cfg_enable_fip) { if (!phba->cfg_enable_fip) {
*boot_flag = 0; *boot_flag = 0;
*addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov,
...@@ -1216,6 +1221,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, ...@@ -1216,6 +1221,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
*boot_flag = 0; *boot_flag = 0;
*addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov,
new_fcf_record); new_fcf_record);
/*
* When there are no FCF connect entries, use driver's default
* addressing mode - FPMA.
*/
if (*addr_mode & LPFC_FCF_FPMA)
*addr_mode = LPFC_FCF_FPMA;
*vlan_id = 0xFFFF; *vlan_id = 0xFFFF;
return 1; return 1;
} }
...@@ -1240,6 +1253,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, ...@@ -1240,6 +1253,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
continue; continue;
} }
/*
* If connection record does not support any addressing mode,
* skip the FCF record.
*/
if (!(bf_get(lpfc_fcf_record_mac_addr_prov, new_fcf_record)
& (LPFC_FCF_FPMA | LPFC_FCF_SPMA)))
continue;
/* /*
* Check if the connection record specifies a required * Check if the connection record specifies a required
* addressing mode. * addressing mode.
...@@ -1272,6 +1293,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, ...@@ -1272,6 +1293,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
else else
*boot_flag = 0; *boot_flag = 0;
/*
* If user did not specify any addressing mode, or if the
* prefered addressing mode specified by user is not supported
* by FCF, allow fabric to pick the addressing mode.
*/
*addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov,
new_fcf_record); new_fcf_record);
/* /*
...@@ -1297,12 +1323,6 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, ...@@ -1297,12 +1323,6 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba,
!(conn_entry->conn_rec.flags & FCFCNCT_AM_SPMA) && !(conn_entry->conn_rec.flags & FCFCNCT_AM_SPMA) &&
(*addr_mode & LPFC_FCF_FPMA)) (*addr_mode & LPFC_FCF_FPMA))
*addr_mode = LPFC_FCF_FPMA; *addr_mode = LPFC_FCF_FPMA;
/*
* If user did not specify any addressing mode, use FPMA if
* possible else use SPMA.
*/
else if (*addr_mode & LPFC_FCF_FPMA)
*addr_mode = LPFC_FCF_FPMA;
if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID) if (conn_entry->conn_rec.flags & FCFCNCT_VLAN_VALID)
*vlan_id = conn_entry->conn_rec.vlan_tag; *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,7 +1884,7 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
vport->fc_flag &= ~FC_BYPASSED_MODE; vport->fc_flag &= ~FC_BYPASSED_MODE;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
if (((phba->fc_eventTag + 1) < la->eventTag) || if ((phba->fc_eventTag < la->eventTag) ||
(phba->fc_eventTag == la->eventTag)) { (phba->fc_eventTag == la->eventTag)) {
phba->fc_stat.LinkMultiEvent++; phba->fc_stat.LinkMultiEvent++;
if (la->attType == AT_LINK_UP) if (la->attType == AT_LINK_UP)
...@@ -2925,6 +2945,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -2925,6 +2945,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
lpfc_no_rpi(phba, ndlp); lpfc_no_rpi(phba, ndlp);
ndlp->nlp_rpi = 0; ndlp->nlp_rpi = 0;
ndlp->nlp_flag &= ~NLP_RPI_VALID; ndlp->nlp_flag &= ~NLP_RPI_VALID;
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
return 1; return 1;
} }
return 0; return 0;
......
...@@ -1128,7 +1128,7 @@ struct fcf_record { ...@@ -1128,7 +1128,7 @@ struct fcf_record {
#define lpfc_fcf_record_mac_5_WORD word4 #define lpfc_fcf_record_mac_5_WORD word4
#define lpfc_fcf_record_fcf_avail_SHIFT 16 #define lpfc_fcf_record_fcf_avail_SHIFT 16
#define lpfc_fcf_record_fcf_avail_MASK 0x000000FF #define lpfc_fcf_record_fcf_avail_MASK 0x000000FF
#define lpfc_fcf_record_fc_avail_WORD word4 #define lpfc_fcf_record_fcf_avail_WORD word4
#define lpfc_fcf_record_mac_addr_prov_SHIFT 24 #define lpfc_fcf_record_mac_addr_prov_SHIFT 24
#define lpfc_fcf_record_mac_addr_prov_MASK 0x000000FF #define lpfc_fcf_record_mac_addr_prov_MASK 0x000000FF
#define lpfc_fcf_record_mac_addr_prov_WORD word4 #define lpfc_fcf_record_mac_addr_prov_WORD word4
......
...@@ -1715,8 +1715,10 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq) ...@@ -1715,8 +1715,10 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq)
/* Set up host requested features. */ /* Set up host requested features. */
bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1);
/* Virtual fabrics and FIPs are not supported yet. */ if (phba->cfg_enable_fip)
bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0); bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0);
else
bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 1);
/* Enable DIF (block guard) only if configured to do so. */ /* Enable DIF (block guard) only if configured to do so. */
if (phba->cfg_enable_bg) if (phba->cfg_enable_bg)
......
...@@ -497,7 +497,7 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -497,7 +497,7 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
else else
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
if ((ndlp->nlp_type & NLP_FABRIC) && if ((ndlp->nlp_DID == Fabric_DID) &&
vport->port_type == LPFC_NPIV_PORT) { vport->port_type == LPFC_NPIV_PORT) {
lpfc_linkdown_port(vport); lpfc_linkdown_port(vport);
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
......
...@@ -4491,7 +4491,9 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) ...@@ -4491,7 +4491,9 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
rc = -ENODEV; rc = -ENODEV;
goto out_free_vpd; goto out_free_vpd;
} }
/* Temporary initialization of lpfc_fip_flag to non-fip */ if (phba->cfg_enable_fip)
bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 1);
else
bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0); bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0);
/* Set up all the queues to the device */ /* Set up all the queues to the device */
...@@ -5856,18 +5858,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, ...@@ -5856,18 +5858,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
fip = bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags); fip = bf_get(lpfc_fip_flag, &phba->sli4_hba.sli4_flags);
/* The fcp commands will set command type */ /* The fcp commands will set command type */
if ((!(iocbq->iocb_flag & LPFC_IO_FCP)) && (!fip)) if (iocbq->iocb_flag & LPFC_IO_FCP)
command_type = ELS_COMMAND_NON_FIP;
else if (!(iocbq->iocb_flag & LPFC_IO_FCP))
command_type = ELS_COMMAND_FIP;
else if (iocbq->iocb_flag & LPFC_IO_FCP)
command_type = FCP_COMMAND; command_type = FCP_COMMAND;
else { else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS))
lpfc_printf_log(phba, KERN_ERR, LOG_SLI, command_type = ELS_COMMAND_FIP;
"2019 Invalid cmd 0x%x\n", else
iocbq->iocb.ulpCommand); command_type = ELS_COMMAND_NON_FIP;
return IOCB_ERROR;
}
/* Some of the fields are in the right position already */ /* Some of the fields are in the right position already */
memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe));
abort_tag = (uint32_t) iocbq->iotag; abort_tag = (uint32_t) iocbq->iotag;
...@@ -11467,6 +11464,7 @@ lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba, ...@@ -11467,6 +11464,7 @@ lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba,
bf_set(lpfc_fcf_record_fc_map_1, fcf_record, phba->fc_map[1]); bf_set(lpfc_fcf_record_fc_map_1, fcf_record, phba->fc_map[1]);
bf_set(lpfc_fcf_record_fc_map_2, fcf_record, phba->fc_map[2]); bf_set(lpfc_fcf_record_fc_map_2, fcf_record, phba->fc_map[2]);
bf_set(lpfc_fcf_record_fcf_valid, fcf_record, 1); bf_set(lpfc_fcf_record_fcf_valid, fcf_record, 1);
bf_set(lpfc_fcf_record_fcf_avail, fcf_record, 1);
bf_set(lpfc_fcf_record_fcf_index, fcf_record, fcf_index); bf_set(lpfc_fcf_record_fcf_index, fcf_record, fcf_index);
bf_set(lpfc_fcf_record_mac_addr_prov, fcf_record, bf_set(lpfc_fcf_record_mac_addr_prov, fcf_record,
LPFC_FCF_FPMA | LPFC_FCF_SPMA); LPFC_FCF_FPMA | LPFC_FCF_SPMA);
......
...@@ -56,6 +56,7 @@ struct lpfc_iocbq { ...@@ -56,6 +56,7 @@ struct lpfc_iocbq {
#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */ #define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */
#define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */ #define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */
#define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */ #define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */
#define LPFC_FIP_ELS 0x40
uint8_t abort_count; uint8_t abort_count;
uint8_t rsvd2; uint8_t rsvd2;
......
...@@ -695,8 +695,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -695,8 +695,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
} }
vport->unreg_vpi_cmpl = VPORT_INVAL; vport->unreg_vpi_cmpl = VPORT_INVAL;
timeout = msecs_to_jiffies(phba->fc_ratov * 2000); timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
goto skip_logo;
if (!lpfc_issue_els_npiv_logo(vport, ndlp)) if (!lpfc_issue_els_npiv_logo(vport, ndlp))
while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout) while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
timeout = schedule_timeout(timeout); timeout = schedule_timeout(timeout);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment