Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: lpfc: NVME Target: Merge into FC discovery

NVME Target: Merge into FC discovery

Adds NVME PRLI handling and Nameserver registrations for NVME

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
8c258641 2d7dbc4c

+167 -14
+7 -1
drivers/scsi/lpfc/lpfc_ct.c
··· 1433 1433 if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || 1434 1434 (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) && 1435 1435 (context == FC_TYPE_NVME)) { 1436 - lpfc_nvme_update_localport(vport); 1436 + if ((vport == phba->pport) && phba->nvmet_support) { 1437 + CtReq->un.rff.fbits = (FC4_FEATURE_TARGET | 1438 + FC4_FEATURE_NVME_DISC); 1439 + /* todo: update targetport attributes */ 1440 + } else { 1441 + lpfc_nvme_update_localport(vport); 1442 + } 1437 1443 CtReq->un.rff.type_code = context; 1438 1444 1439 1445 } else if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
+56 -5
drivers/scsi/lpfc/lpfc_els.c
··· 2001 2001 sp->cmn.fcphHigh = FC_PH3; 2002 2002 2003 2003 sp->cmn.valid_vendor_ver_level = 0; 2004 + memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion)); 2004 2005 2005 2006 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, 2006 2007 "Issue PLOGI: did:x%x", 2007 2008 did, 0, 0); 2009 + 2010 + /* If our firmware supports this feature, convey that 2011 + * information to the target using the vendor specific field. 2012 + */ 2013 + if (phba->sli.sli_flag & LPFC_SLI_SUPPRESS_RSP) { 2014 + sp->cmn.valid_vendor_ver_level = 1; 2015 + sp->un.vv.vid = cpu_to_be32(LPFC_VV_EMLX_ID); 2016 + sp->un.vv.flags = cpu_to_be32(LPFC_VV_SUPPRESS_RSP); 2017 + } 2008 2018 2009 2019 phba->fc_stat.elsXmitPLOGI++; 2010 2020 elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; ··· 2217 2207 !phba->nvmet_support) 2218 2208 bf_set(prli_fba, npr_nvme, 1); 2219 2209 2220 - bf_set(prli_init, npr_nvme, 1); 2210 + if (phba->nvmet_support) { 2211 + bf_set(prli_tgt, npr_nvme, 1); 2212 + bf_set(prli_disc, npr_nvme, 1); 2213 + 2214 + } else { 2215 + bf_set(prli_init, npr_nvme, 1); 2216 + } 2221 2217 npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); 2222 2218 npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); 2223 2219 elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ; ··· 2635 2619 phba->pport->fc_myDID = 0; 2636 2620 2637 2621 if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || 2638 - (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) 2639 - lpfc_nvme_update_localport(phba->pport); 2622 + (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { 2623 + if (!phba->nvmet_support) 2624 + lpfc_nvme_update_localport(phba->pport); 2625 + /* todo: tgt: update targetport attributes */ 2626 + } 2640 2627 2641 2628 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); 2642 2629 if (mbox) { ··· 4093 4074 sizeof(struct lpfc_name)); 4094 4075 memcpy(&sp->nodeName, &vport->fc_sparam.nodeName, 4095 4076 sizeof(struct lpfc_name)); 4096 - } else 4077 + } else { 4097 4078 memcpy(pcmd, &vport->fc_sparam, 4098 4079 sizeof(struct serv_parm)); 4080 + 4081 + sp->cmn.valid_vendor_ver_level = 0; 4082 + memset(sp->un.vendorVersion, 0, 4083 + sizeof(sp->un.vendorVersion)); 4084 + 4085 + /* If our firmware supports this feature, convey that 4086 + * info to the target using the vendor specific field. 4087 + */ 4088 + if (phba->sli.sli_flag & LPFC_SLI_SUPPRESS_RSP) { 4089 + sp->cmn.valid_vendor_ver_level = 1; 4090 + sp->un.vv.vid = cpu_to_be32(LPFC_VV_EMLX_ID); 4091 + sp->un.vv.flags = 4092 + cpu_to_be32(LPFC_VV_SUPPRESS_RSP); 4093 + } 4094 + } 4099 4095 4100 4096 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, 4101 4097 "Issue ACC FLOGI/PLOGI: did:x%x flg:x%x", ··· 4431 4397 bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE); 4432 4398 bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */ 4433 4399 bf_set(prli_acc_rsp_code, npr_nvme, PRLI_REQ_EXECUTED); 4434 - bf_set(prli_init, npr_nvme, 1); 4400 + if (phba->nvmet_support) { 4401 + bf_set(prli_tgt, npr_nvme, 1); 4402 + bf_set(prli_disc, npr_nvme, 1); 4403 + if (phba->cfg_nvme_enable_fb) { 4404 + bf_set(prli_fba, npr_nvme, 1); 4405 + 4406 + /* TBD. Target mode needs to post buffers 4407 + * that support the configured first burst 4408 + * byte size. 4409 + */ 4410 + bf_set(prli_fb_sz, npr_nvme, 4411 + phba->cfg_nvmet_fb_size); 4412 + } 4413 + } else { 4414 + bf_set(prli_init, npr_nvme, 1); 4415 + } 4435 4416 4436 4417 lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, 4437 4418 "6015 NVME issue PRLI ACC word1 x%08x " ··· 5863 5814 if (!NLP_CHK_NODE_ACT(ndlp) || 5864 5815 (ndlp->nlp_state == NLP_STE_UNUSED_NODE) || 5865 5816 !lpfc_rscn_payload_check(vport, ndlp->nlp_DID)) 5817 + continue; 5818 + if (vport->phba->nvmet_support) 5866 5819 continue; 5867 5820 lpfc_disc_state_machine(vport, ndlp, NULL, 5868 5821 NLP_EVT_DEVICE_RECOVERY);
+23 -4
drivers/scsi/lpfc/lpfc_hbadisc.c
··· 910 910 vports[i]->fc_myDID = 0; 911 911 912 912 if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || 913 - (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) 914 - lpfc_nvme_update_localport(vports[i]); 913 + (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { 914 + if (!phba->nvmet_support) 915 + lpfc_nvme_update_localport(vports[i]); 916 + /* todo: tgt: update targetport attributes */ 917 + } 915 918 } 916 919 } 917 920 lpfc_destroy_vport_work_array(phba, vports); ··· 3586 3583 vport->fc_myDID = 0; 3587 3584 3588 3585 if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || 3589 - (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) 3590 - lpfc_nvme_update_localport(vport); 3586 + (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { 3587 + if (!phba->nvmet_support) 3588 + lpfc_nvme_update_localport(vport); 3589 + /* todo: update targetport attributes */ 3590 + } 3591 3591 goto out; 3592 3592 } 3593 3593 ··· 4181 4175 */ 4182 4176 vport->phba->nport_event_cnt++; 4183 4177 lpfc_nvme_register_port(vport, ndlp); 4178 + } else { 4179 + /* Just take an NDLP ref count since the 4180 + * target does not register rports. 4181 + */ 4182 + lpfc_nlp_get(ndlp); 4184 4183 } 4185 4184 } 4186 4185 } ··· 5107 5096 return NULL; 5108 5097 lpfc_nlp_init(vport, ndlp, did); 5109 5098 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 5099 + if (vport->phba->nvmet_support) 5100 + return ndlp; 5110 5101 spin_lock_irq(shost->host_lock); 5111 5102 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 5112 5103 spin_unlock_irq(shost->host_lock); ··· 5117 5104 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_NPR_NODE); 5118 5105 if (!ndlp) 5119 5106 return NULL; 5107 + if (vport->phba->nvmet_support) 5108 + return ndlp; 5120 5109 spin_lock_irq(shost->host_lock); 5121 5110 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 5122 5111 spin_unlock_irq(shost->host_lock); ··· 5138 5123 * delay timeout is not needed. 5139 5124 */ 5140 5125 lpfc_cancel_retry_delay_tmo(vport, ndlp); 5126 + if (vport->phba->nvmet_support) 5127 + return ndlp; 5141 5128 spin_lock_irq(shost->host_lock); 5142 5129 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 5143 5130 spin_unlock_irq(shost->host_lock); ··· 5155 5138 ndlp->nlp_flag & NLP_RCV_PLOGI) 5156 5139 return NULL; 5157 5140 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 5141 + if (vport->phba->nvmet_support) 5142 + return ndlp; 5158 5143 spin_lock_irq(shost->host_lock); 5159 5144 ndlp->nlp_flag |= NLP_NPR_2B_DISC; 5160 5145 spin_unlock_irq(shost->host_lock);
+9 -1
drivers/scsi/lpfc/lpfc_hw.h
··· 515 515 struct class_parms cls2; 516 516 struct class_parms cls3; 517 517 struct class_parms cls4; 518 - uint8_t vendorVersion[16]; 518 + union { 519 + uint8_t vendorVersion[16]; 520 + struct { 521 + uint32_t vid; 522 + #define LPFC_VV_EMLX_ID 0x454d4c58 /* EMLX */ 523 + uint32_t flags; 524 + #define LPFC_VV_SUPPRESS_RSP 1 525 + } vv; 526 + } un; 519 527 }; 520 528 521 529 /*
+72 -3
drivers/scsi/lpfc/lpfc_nportdisc.c
··· 288 288 uint32_t ed_tov; 289 289 LPFC_MBOXQ_t *mbox; 290 290 struct ls_rjt stat; 291 + uint32_t vid, flag; 291 292 int rc; 292 293 293 294 memset(&stat, 0, sizeof (struct ls_rjt)); ··· 422 421 } 423 422 424 423 lpfc_can_disctmo(vport); 424 + } 425 + 426 + ndlp->nlp_flag &= ~NLP_SUPPRESS_RSP; 427 + if ((phba->sli.sli_flag & LPFC_SLI_SUPPRESS_RSP) && 428 + sp->cmn.valid_vendor_ver_level) { 429 + vid = be32_to_cpu(sp->un.vv.vid); 430 + flag = be32_to_cpu(sp->un.vv.flags); 431 + if ((vid == LPFC_VV_EMLX_ID) && (flag & LPFC_VV_SUPPRESS_RSP)) 432 + ndlp->nlp_flag |= NLP_SUPPRESS_RSP; 425 433 } 426 434 427 435 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); ··· 754 744 } 755 745 if (npr->Retry) 756 746 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; 747 + 748 + /* If this driver is in nvme target mode, set the ndlp's fc4 749 + * type to NVME provided the PRLI response claims NVME FC4 750 + * type. Target mode does not issue gft_id so doesn't get 751 + * the fc4 type set until now. 752 + */ 753 + if ((phba->nvmet_support) && (npr->prliType == PRLI_NVME_TYPE)) 754 + ndlp->nlp_fc4_type |= NLP_FC4_NVME; 757 755 } 758 756 if (rport) { 759 757 /* We need to update the rport role values */ ··· 1059 1041 struct lpfc_iocbq *cmdiocb, *rspiocb; 1060 1042 struct lpfc_dmabuf *pcmd, *prsp, *mp; 1061 1043 uint32_t *lp; 1044 + uint32_t vid, flag; 1062 1045 IOCB_t *irsp; 1063 1046 struct serv_parm *sp; 1064 1047 uint32_t ed_tov; ··· 1126 1107 if (sp->cmn.edtovResolution) { 1127 1108 /* E_D_TOV ticks are in nanoseconds */ 1128 1109 ed_tov = (phba->fc_edtov + 999999) / 1000000; 1110 + } 1111 + 1112 + ndlp->nlp_flag &= ~NLP_SUPPRESS_RSP; 1113 + if ((phba->sli.sli_flag & LPFC_SLI_SUPPRESS_RSP) && 1114 + sp->cmn.valid_vendor_ver_level) { 1115 + vid = be32_to_cpu(sp->un.vv.vid); 1116 + flag = be32_to_cpu(sp->un.vv.flags); 1117 + if ((vid == LPFC_VV_EMLX_ID) && 1118 + (flag & LPFC_VV_SUPPRESS_RSP)) 1119 + ndlp->nlp_flag |= NLP_SUPPRESS_RSP; 1129 1120 } 1130 1121 1131 1122 /* ··· 1533 1504 uint32_t evt) 1534 1505 { 1535 1506 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; 1507 + struct ls_rjt stat; 1536 1508 1537 - /* Initiator mode. */ 1538 - lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); 1509 + if (vport->phba->nvmet_support) { 1510 + /* NVME Target mode. Handle and respond to the PRLI and 1511 + * transition to UNMAPPED provided the RPI has completed 1512 + * registration. 1513 + */ 1514 + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { 1515 + lpfc_rcv_prli(vport, ndlp, cmdiocb); 1516 + lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); 1517 + lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); 1518 + } else { 1519 + /* RPI registration has not completed. Reject the PRLI 1520 + * to prevent an illegal state transition when the 1521 + * rpi registration does complete. 1522 + */ 1523 + lpfc_printf_vlog(vport, KERN_WARNING, LOG_NVME_DISC, 1524 + "6115 NVMET ndlp rpi %d state " 1525 + "unknown, state x%x flags x%08x\n", 1526 + ndlp->nlp_rpi, ndlp->nlp_state, 1527 + ndlp->nlp_flag); 1528 + memset(&stat, 0, sizeof(struct ls_rjt)); 1529 + stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 1530 + stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; 1531 + lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, 1532 + ndlp, NULL); 1533 + } 1534 + } else { 1535 + /* Initiator mode. */ 1536 + lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); 1537 + } 1539 1538 1540 1539 return ndlp->nlp_state; 1541 1540 } ··· 1725 1668 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); 1726 1669 lpfc_issue_els_prli(vport, ndlp, 0); 1727 1670 } else { 1728 - /* Only Fabric ports should transition */ 1671 + if ((vport->fc_flag & FC_PT2PT) && phba->nvmet_support) 1672 + phba->targetport->port_id = vport->fc_myDID; 1673 + 1674 + /* Only Fabric ports should transition. NVME target 1675 + * must complete PRLI. 1676 + */ 1729 1677 if (ndlp->nlp_type & NLP_FABRIC) { 1730 1678 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; 1731 1679 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); ··· 1775 1713 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; 1776 1714 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 1777 1715 spin_lock_irq(shost->host_lock); 1716 + 1717 + /* If we are a target we won't immediately transition into PRLI, 1718 + * so if REG_LOGIN already completed we don't need to ignore it. 1719 + */ 1720 + if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED) || 1721 + !vport->phba->nvmet_support) 1722 + ndlp->nlp_flag |= NLP_IGNR_REG_CMPL; 1778 1723 1779 1724 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); 1780 1725 spin_unlock_irq(shost->host_lock);