From 0c2875893ef27b93d5d3221f8f98ae944d6be5fa Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 10 Jun 2009 17:22:56 -0400 Subject: [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 Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 13 +++++++++++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 35 ++++++++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_hw4.h | 2 +- drivers/scsi/lpfc/lpfc_mbox.c | 6 ++++-- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 24 +++++++++++------------- drivers/scsi/lpfc/lpfc_sli.h | 1 + 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 2aabaf9c405..f72fdf23bf1 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, if (elsiocb == 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; /* fill in BDEs for command */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 35c41ae75be..ed46b24a338 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, { 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) { *boot_flag = 0; *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, @@ -1216,6 +1221,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, *boot_flag = 0; *addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov, 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; return 1; } @@ -1240,6 +1253,14 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, 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 * addressing mode. @@ -1272,6 +1293,11 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, else *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, new_fcf_record); /* @@ -1297,12 +1323,6 @@ lpfc_match_fcf_conn_list(struct lpfc_hba *phba, !(conn_entry->conn_rec.flags & FCFCNCT_AM_SPMA) && (*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) *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) vport->fc_flag &= ~FC_BYPASSED_MODE; 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_stat.LinkMultiEvent++; if (la->attType == AT_LINK_UP) @@ -2925,6 +2945,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_no_rpi(phba, ndlp); ndlp->nlp_rpi = 0; ndlp->nlp_flag &= ~NLP_RPI_VALID; + ndlp->nlp_flag &= ~NLP_NPR_ADISC; return 1; } return 0; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 749811a1627..2995d128f07 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1128,7 +1128,7 @@ struct fcf_record { #define lpfc_fcf_record_mac_5_WORD word4 #define lpfc_fcf_record_fcf_avail_SHIFT 16 #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_MASK 0x000000FF #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 b9b451c0901..bb3dc1dcffe 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) /* Set up host requested features. */ bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); - /* Virtual fabrics and FIPs are not supported yet. */ - bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0); + if (phba->cfg_enable_fip) + 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. */ if (phba->cfg_enable_bg) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 09f659f77bb..3e74136f1ed 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, lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); else 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) { lpfc_linkdown_port(vport); 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 b8cf0a1b138..ba698d5f31a 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) rc = -ENODEV; goto out_free_vpd; } - /* Temporary initialization of lpfc_fip_flag to non-fip */ - bf_set(lpfc_fip_flag, &phba->sli4_hba.sli4_flags, 0); + 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); /* Set up all the queues to the device */ rc = lpfc_sli4_queue_setup(phba); @@ -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); /* The fcp commands will set command type */ - if ((!(iocbq->iocb_flag & LPFC_IO_FCP)) && (!fip)) - 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) + if (iocbq->iocb_flag & LPFC_IO_FCP) command_type = FCP_COMMAND; - else { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "2019 Invalid cmd 0x%x\n", - iocbq->iocb.ulpCommand); - return IOCB_ERROR; - } + else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS)) + command_type = ELS_COMMAND_FIP; + else + command_type = ELS_COMMAND_NON_FIP; + /* Some of the fields are in the right position already */ memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); abort_tag = (uint32_t) iocbq->iotag; @@ -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_2, fcf_record, phba->fc_map[2]); 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_mac_addr_prov, fcf_record, LPFC_FCF_FPMA | LPFC_FCF_SPMA); diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 7d37eb7459b..3c53316cf6d 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -56,6 +56,7 @@ struct lpfc_iocbq { #define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */ #define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */ #define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */ +#define LPFC_FIP_ELS 0x40 uint8_t abort_count; uint8_t rsvd2; diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index a6313ee84ac..e0b49922193 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) } vport->unreg_vpi_cmpl = VPORT_INVAL; 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)) while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout) timeout = schedule_timeout(timeout); -- cgit v1.2.3