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

Configure Feed

Select the types of activity you want to include in your feed.

scsi: lpfc: vmid: Implement ELS commands for appid

Implement ELS commands QFPA and UVEM for the priority tagging appid
support.

Link: https://lore.kernel.org/r/20210608043556.274139-8-muneendra.kumar@broadcom.com
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Muneendra Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Gaurav Srivastava and committed by
Martin K. Petersen
7e473de7 5e633302

+362 -4
+362 -4
drivers/scsi/lpfc/lpfc_els.c
··· 25 25 #include <linux/pci.h> 26 26 #include <linux/slab.h> 27 27 #include <linux/interrupt.h> 28 + #include <linux/delay.h> 28 29 29 30 #include <scsi/scsi.h> 30 31 #include <scsi/scsi_device.h> ··· 56 55 struct lpfc_nodelist *ndlp, uint8_t retry); 57 56 static int lpfc_issue_fabric_iocb(struct lpfc_hba *phba, 58 57 struct lpfc_iocbq *iocb); 58 + static void lpfc_cmpl_els_uvem(struct lpfc_hba *, struct lpfc_iocbq *, 59 + struct lpfc_iocbq *); 59 60 60 61 static int lpfc_max_els_tries = 3; 62 + 63 + static void lpfc_init_cs_ctl_bitmap(struct lpfc_vport *vport); 64 + static void lpfc_vmid_set_cs_ctl_range(struct lpfc_vport *vport, u32 min, u32 max); 65 + static void lpfc_vmid_put_cs_ctl(struct lpfc_vport *vport, u32 ctcl_vmid); 61 66 62 67 /** 63 68 * lpfc_els_chk_latt - Check host link attention event for a vport ··· 321 314 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, 322 315 "0116 Xmit ELS command x%x to remote " 323 316 "NPORT x%x I/O tag: x%x, port state:x%x " 324 - "rpi x%x fc_flag:x%x\n", 317 + "rpi x%x fc_flag:x%x nlp_flag:x%x vport:x%p\n", 325 318 elscmd, did, elsiocb->iotag, 326 319 vport->port_state, ndlp->nlp_rpi, 327 - vport->fc_flag); 320 + vport->fc_flag, ndlp->nlp_flag, vport); 328 321 } else { 329 322 /* Xmit ELS response <elsCmd> to remote NPORT <did> */ 330 323 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ··· 1119 1112 /* FLOGI completes successfully */ 1120 1113 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, 1121 1114 "0101 FLOGI completes successfully, I/O tag:x%x, " 1122 - "xri x%x Data: x%x x%x x%x x%x x%x %x\n", 1115 + "xri x%x Data: x%x x%x x%x x%x x%x x%x x%x\n", 1123 1116 cmdiocb->iotag, cmdiocb->sli4_xritag, 1124 1117 irsp->un.ulpWord[4], sp->cmn.e_d_tov, 1125 1118 sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution, 1126 - vport->port_state, vport->fc_flag); 1119 + vport->port_state, vport->fc_flag, 1120 + sp->cmn.priority_tagging); 1121 + 1122 + if (sp->cmn.priority_tagging) 1123 + vport->vmid_flag |= LPFC_VMID_ISSUE_QFPA; 1127 1124 1128 1125 if (vport->port_state == LPFC_FLOGI) { 1129 1126 /* ··· 1318 1307 sp->cmn.fcphLow = FC_PH3; 1319 1308 if (sp->cmn.fcphHigh < FC_PH3) 1320 1309 sp->cmn.fcphHigh = FC_PH3; 1310 + 1311 + /* Determine if switch supports priority tagging */ 1312 + if (phba->cfg_vmid_priority_tagging) { 1313 + sp->cmn.priority_tagging = 1; 1314 + /* lpfc_vmid_host_uuid is combination of wwpn and wwnn */ 1315 + if (uuid_is_null((uuid_t *)vport->lpfc_vmid_host_uuid)) { 1316 + memcpy(vport->lpfc_vmid_host_uuid, phba->wwpn, 1317 + sizeof(phba->wwpn)); 1318 + memcpy(&vport->lpfc_vmid_host_uuid[8], phba->wwnn, 1319 + sizeof(phba->wwnn)); 1320 + } 1321 + } 1321 1322 1322 1323 if (phba->sli_rev == LPFC_SLI_REV4) { 1323 1324 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == ··· 1957 1934 struct lpfc_nodelist *ndlp, *free_ndlp; 1958 1935 struct lpfc_dmabuf *prsp; 1959 1936 int disc; 1937 + struct serv_parm *sp = NULL; 1960 1938 1961 1939 /* we pass cmdiocb to state machine which needs rspiocb as well */ 1962 1940 cmdiocb->context_un.rsp_iocb = rspiocb; ··· 2059 2035 cmdiocb->context2)->list.next, 2060 2036 struct lpfc_dmabuf, list); 2061 2037 ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp); 2038 + 2039 + sp = (struct serv_parm *)((u8 *)prsp->virt + 2040 + sizeof(u32)); 2041 + 2042 + ndlp->vmid_support = 0; 2043 + if ((phba->cfg_vmid_app_header && sp->cmn.app_hdr_support) || 2044 + (phba->cfg_vmid_priority_tagging && 2045 + sp->cmn.priority_tagging)) { 2046 + lpfc_printf_log(phba, KERN_DEBUG, LOG_ELS, 2047 + "4018 app_hdr_support %d tagging %d DID x%x\n", 2048 + sp->cmn.app_hdr_support, 2049 + sp->cmn.priority_tagging, 2050 + ndlp->nlp_DID); 2051 + /* if the dest port supports VMID, mark it in ndlp */ 2052 + ndlp->vmid_support = 1; 2053 + } 2054 + 2062 2055 lpfc_disc_state_machine(vport, ndlp, cmdiocb, 2063 2056 NLP_EVT_CMPL_PLOGI); 2064 2057 } ··· 2197 2156 sp->cmn.valid_vendor_ver_level = 0; 2198 2157 memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion)); 2199 2158 sp->cmn.bbRcvSizeMsb &= 0xF; 2159 + 2160 + /* Check if the destination port supports VMID */ 2161 + ndlp->vmid_support = 0; 2162 + if (vport->vmid_priority_tagging) 2163 + sp->cmn.priority_tagging = 1; 2164 + else if (phba->cfg_vmid_app_header && 2165 + bf_get(lpfc_ftr_ashdr, &phba->sli4_hba.sli4_flags)) 2166 + sp->cmn.app_hdr_support = 1; 2200 2167 2201 2168 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, 2202 2169 "Issue PLOGI: did:x%x", ··· 10514 10465 lpfc_unreg_rpi(vport, ndlp); 10515 10466 } 10516 10467 10468 + static void lpfc_init_cs_ctl_bitmap(struct lpfc_vport *vport) 10469 + { 10470 + bitmap_zero(vport->vmid_priority_range, LPFC_VMID_MAX_PRIORITY_RANGE); 10471 + } 10472 + 10473 + static void 10474 + lpfc_vmid_set_cs_ctl_range(struct lpfc_vport *vport, u32 min, u32 max) 10475 + { 10476 + u32 i; 10477 + 10478 + if ((min > max) || (max > LPFC_VMID_MAX_PRIORITY_RANGE)) 10479 + return; 10480 + 10481 + for (i = min; i <= max; i++) 10482 + set_bit(i, vport->vmid_priority_range); 10483 + } 10484 + 10485 + static void lpfc_vmid_put_cs_ctl(struct lpfc_vport *vport, u32 ctcl_vmid) 10486 + { 10487 + set_bit(ctcl_vmid, vport->vmid_priority_range); 10488 + } 10489 + 10490 + u32 lpfc_vmid_get_cs_ctl(struct lpfc_vport *vport) 10491 + { 10492 + u32 i; 10493 + 10494 + i = find_first_bit(vport->vmid_priority_range, 10495 + LPFC_VMID_MAX_PRIORITY_RANGE); 10496 + 10497 + if (i == LPFC_VMID_MAX_PRIORITY_RANGE) 10498 + return 0; 10499 + 10500 + clear_bit(i, vport->vmid_priority_range); 10501 + return i; 10502 + } 10503 + 10504 + #define MAX_PRIORITY_DESC 255 10505 + 10506 + static void 10507 + lpfc_cmpl_els_qfpa(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, 10508 + struct lpfc_iocbq *rspiocb) 10509 + { 10510 + struct lpfc_vport *vport = cmdiocb->vport; 10511 + struct priority_range_desc *desc; 10512 + struct lpfc_dmabuf *prsp = NULL; 10513 + struct lpfc_vmid_priority_range *vmid_range = NULL; 10514 + u32 *data; 10515 + struct lpfc_dmabuf *dmabuf = cmdiocb->context2; 10516 + IOCB_t *irsp = &rspiocb->iocb; 10517 + u8 *pcmd, max_desc; 10518 + u32 len, i; 10519 + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)cmdiocb->context1; 10520 + 10521 + prsp = list_get_first(&dmabuf->list, struct lpfc_dmabuf, list); 10522 + if (!prsp) 10523 + goto out; 10524 + 10525 + pcmd = prsp->virt; 10526 + data = (u32 *)pcmd; 10527 + if (data[0] == ELS_CMD_LS_RJT) { 10528 + lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI, 10529 + "3277 QFPA LS_RJT x%x x%x\n", 10530 + data[0], data[1]); 10531 + goto out; 10532 + } 10533 + if (irsp->ulpStatus) { 10534 + lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, 10535 + "6529 QFPA failed with status x%x x%x\n", 10536 + irsp->ulpStatus, irsp->un.ulpWord[4]); 10537 + goto out; 10538 + } 10539 + 10540 + if (!vport->qfpa_res) { 10541 + max_desc = FCELSSIZE / sizeof(*vport->qfpa_res); 10542 + vport->qfpa_res = kcalloc(max_desc, sizeof(*vport->qfpa_res), 10543 + GFP_KERNEL); 10544 + if (!vport->qfpa_res) 10545 + goto out; 10546 + } 10547 + 10548 + len = *((u32 *)(pcmd + 4)); 10549 + len = be32_to_cpu(len); 10550 + memcpy(vport->qfpa_res, pcmd, len + 8); 10551 + len = len / LPFC_PRIORITY_RANGE_DESC_SIZE; 10552 + 10553 + desc = (struct priority_range_desc *)(pcmd + 8); 10554 + vmid_range = vport->vmid_priority.vmid_range; 10555 + if (!vmid_range) { 10556 + vmid_range = kcalloc(MAX_PRIORITY_DESC, sizeof(*vmid_range), 10557 + GFP_KERNEL); 10558 + if (!vmid_range) { 10559 + kfree(vport->qfpa_res); 10560 + goto out; 10561 + } 10562 + vport->vmid_priority.vmid_range = vmid_range; 10563 + } 10564 + vport->vmid_priority.num_descriptors = len; 10565 + 10566 + for (i = 0; i < len; i++, vmid_range++, desc++) { 10567 + lpfc_printf_vlog(vport, KERN_DEBUG, LOG_ELS, 10568 + "6539 vmid values low=%d, high=%d, qos=%d, " 10569 + "local ve id=%d\n", desc->lo_range, 10570 + desc->hi_range, desc->qos_priority, 10571 + desc->local_ve_id); 10572 + 10573 + vmid_range->low = desc->lo_range << 1; 10574 + if (desc->local_ve_id == QFPA_ODD_ONLY) 10575 + vmid_range->low++; 10576 + if (desc->qos_priority) 10577 + vport->vmid_flag |= LPFC_VMID_QOS_ENABLED; 10578 + vmid_range->qos = desc->qos_priority; 10579 + 10580 + vmid_range->high = desc->hi_range << 1; 10581 + if ((desc->local_ve_id == QFPA_ODD_ONLY) || 10582 + (desc->local_ve_id == QFPA_EVEN_ODD)) 10583 + vmid_range->high++; 10584 + } 10585 + lpfc_init_cs_ctl_bitmap(vport); 10586 + for (i = 0; i < vport->vmid_priority.num_descriptors; i++) { 10587 + lpfc_vmid_set_cs_ctl_range(vport, 10588 + vport->vmid_priority.vmid_range[i].low, 10589 + vport->vmid_priority.vmid_range[i].high); 10590 + } 10591 + 10592 + vport->vmid_flag |= LPFC_VMID_QFPA_CMPL; 10593 + out: 10594 + lpfc_els_free_iocb(phba, cmdiocb); 10595 + lpfc_nlp_put(ndlp); 10596 + } 10597 + 10598 + int lpfc_issue_els_qfpa(struct lpfc_vport *vport) 10599 + { 10600 + struct lpfc_hba *phba = vport->phba; 10601 + struct lpfc_nodelist *ndlp; 10602 + struct lpfc_iocbq *elsiocb; 10603 + u8 *pcmd; 10604 + int ret; 10605 + 10606 + ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); 10607 + if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) 10608 + return -ENXIO; 10609 + 10610 + elsiocb = lpfc_prep_els_iocb(vport, 1, LPFC_QFPA_SIZE, 2, ndlp, 10611 + ndlp->nlp_DID, ELS_CMD_QFPA); 10612 + if (!elsiocb) 10613 + return -ENOMEM; 10614 + 10615 + pcmd = (u8 *)(((struct lpfc_dmabuf *)elsiocb->context2)->virt); 10616 + 10617 + *((u32 *)(pcmd)) = ELS_CMD_QFPA; 10618 + pcmd += 4; 10619 + 10620 + elsiocb->iocb_cmpl = lpfc_cmpl_els_qfpa; 10621 + 10622 + elsiocb->context1 = lpfc_nlp_get(ndlp); 10623 + if (!elsiocb->context1) { 10624 + lpfc_els_free_iocb(vport->phba, elsiocb); 10625 + return -ENXIO; 10626 + } 10627 + 10628 + ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 2); 10629 + if (ret != IOCB_SUCCESS) { 10630 + lpfc_els_free_iocb(phba, elsiocb); 10631 + lpfc_nlp_put(ndlp); 10632 + return -EIO; 10633 + } 10634 + vport->vmid_flag &= ~LPFC_VMID_QOS_ENABLED; 10635 + return 0; 10636 + } 10637 + 10638 + int 10639 + lpfc_vmid_uvem(struct lpfc_vport *vport, 10640 + struct lpfc_vmid *vmid, bool instantiated) 10641 + { 10642 + struct lpfc_vem_id_desc *vem_id_desc; 10643 + struct lpfc_nodelist *ndlp; 10644 + struct lpfc_iocbq *elsiocb; 10645 + struct instantiated_ve_desc *inst_desc; 10646 + struct lpfc_vmid_context *vmid_context; 10647 + u8 *pcmd; 10648 + u32 *len; 10649 + int ret = 0; 10650 + 10651 + ndlp = lpfc_findnode_did(vport, Fabric_DID); 10652 + if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) 10653 + return -ENXIO; 10654 + 10655 + vmid_context = kmalloc(sizeof(*vmid_context), GFP_KERNEL); 10656 + if (!vmid_context) 10657 + return -ENOMEM; 10658 + elsiocb = lpfc_prep_els_iocb(vport, 1, LPFC_UVEM_SIZE, 2, 10659 + ndlp, Fabric_DID, ELS_CMD_UVEM); 10660 + if (!elsiocb) 10661 + goto out; 10662 + 10663 + lpfc_printf_vlog(vport, KERN_DEBUG, LOG_ELS, 10664 + "3427 Host vmid %s %d\n", 10665 + vmid->host_vmid, instantiated); 10666 + vmid_context->vmp = vmid; 10667 + vmid_context->nlp = ndlp; 10668 + vmid_context->instantiated = instantiated; 10669 + elsiocb->vmid_tag.vmid_context = vmid_context; 10670 + pcmd = (u8 *)(((struct lpfc_dmabuf *)elsiocb->context2)->virt); 10671 + 10672 + if (uuid_is_null((uuid_t *)vport->lpfc_vmid_host_uuid)) 10673 + memcpy(vport->lpfc_vmid_host_uuid, vmid->host_vmid, 10674 + LPFC_COMPRESS_VMID_SIZE); 10675 + 10676 + *((u32 *)(pcmd)) = ELS_CMD_UVEM; 10677 + len = (u32 *)(pcmd + 4); 10678 + *len = cpu_to_be32(LPFC_UVEM_SIZE - 8); 10679 + 10680 + vem_id_desc = (struct lpfc_vem_id_desc *)(pcmd + 8); 10681 + vem_id_desc->tag = be32_to_cpu(VEM_ID_DESC_TAG); 10682 + vem_id_desc->length = be32_to_cpu(LPFC_UVEM_VEM_ID_DESC_SIZE); 10683 + memcpy(vem_id_desc->vem_id, vport->lpfc_vmid_host_uuid, 10684 + LPFC_COMPRESS_VMID_SIZE); 10685 + 10686 + inst_desc = (struct instantiated_ve_desc *)(pcmd + 32); 10687 + inst_desc->tag = be32_to_cpu(INSTANTIATED_VE_DESC_TAG); 10688 + inst_desc->length = be32_to_cpu(LPFC_UVEM_VE_MAP_DESC_SIZE); 10689 + memcpy(inst_desc->global_vem_id, vmid->host_vmid, 10690 + LPFC_COMPRESS_VMID_SIZE); 10691 + 10692 + bf_set(lpfc_instantiated_nport_id, inst_desc, vport->fc_myDID); 10693 + bf_set(lpfc_instantiated_local_id, inst_desc, 10694 + vmid->un.cs_ctl_vmid); 10695 + if (instantiated) { 10696 + inst_desc->tag = be32_to_cpu(INSTANTIATED_VE_DESC_TAG); 10697 + } else { 10698 + inst_desc->tag = be32_to_cpu(DEINSTANTIATED_VE_DESC_TAG); 10699 + lpfc_vmid_put_cs_ctl(vport, vmid->un.cs_ctl_vmid); 10700 + } 10701 + inst_desc->word6 = cpu_to_be32(inst_desc->word6); 10702 + 10703 + elsiocb->iocb_cmpl = lpfc_cmpl_els_uvem; 10704 + 10705 + elsiocb->context1 = lpfc_nlp_get(ndlp); 10706 + if (!elsiocb->context1) { 10707 + lpfc_els_free_iocb(vport->phba, elsiocb); 10708 + goto out; 10709 + } 10710 + 10711 + ret = lpfc_sli_issue_iocb(vport->phba, LPFC_ELS_RING, elsiocb, 0); 10712 + if (ret != IOCB_SUCCESS) { 10713 + lpfc_els_free_iocb(vport->phba, elsiocb); 10714 + lpfc_nlp_put(ndlp); 10715 + goto out; 10716 + } 10717 + 10718 + return 0; 10719 + out: 10720 + kfree(vmid_context); 10721 + return -EIO; 10722 + } 10723 + 10724 + static void 10725 + lpfc_cmpl_els_uvem(struct lpfc_hba *phba, struct lpfc_iocbq *icmdiocb, 10726 + struct lpfc_iocbq *rspiocb) 10727 + { 10728 + struct lpfc_vport *vport = icmdiocb->vport; 10729 + struct lpfc_dmabuf *prsp = NULL; 10730 + struct lpfc_vmid_context *vmid_context = 10731 + icmdiocb->vmid_tag.vmid_context; 10732 + struct lpfc_nodelist *ndlp = icmdiocb->context1; 10733 + u8 *pcmd; 10734 + u32 *data; 10735 + IOCB_t *irsp = &rspiocb->iocb; 10736 + struct lpfc_dmabuf *dmabuf = icmdiocb->context2; 10737 + struct lpfc_vmid *vmid; 10738 + 10739 + vmid = vmid_context->vmp; 10740 + if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) 10741 + ndlp = NULL; 10742 + 10743 + prsp = list_get_first(&dmabuf->list, struct lpfc_dmabuf, list); 10744 + if (!prsp) 10745 + goto out; 10746 + pcmd = prsp->virt; 10747 + data = (u32 *)pcmd; 10748 + if (data[0] == ELS_CMD_LS_RJT) { 10749 + lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI, 10750 + "4532 UVEM LS_RJT %x %x\n", data[0], data[1]); 10751 + goto out; 10752 + } 10753 + if (irsp->ulpStatus) { 10754 + lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI, 10755 + "4533 UVEM error status %x: %x\n", 10756 + irsp->ulpStatus, irsp->un.ulpWord[4]); 10757 + goto out; 10758 + } 10759 + spin_lock(&phba->hbalock); 10760 + /* Set IN USE flag */ 10761 + vport->vmid_flag |= LPFC_VMID_IN_USE; 10762 + phba->pport->vmid_flag |= LPFC_VMID_IN_USE; 10763 + spin_unlock(&phba->hbalock); 10764 + 10765 + if (vmid_context->instantiated) { 10766 + write_lock(&vport->vmid_lock); 10767 + vmid->flag |= LPFC_VMID_REGISTERED; 10768 + vmid->flag &= ~LPFC_VMID_REQ_REGISTER; 10769 + write_unlock(&vport->vmid_lock); 10770 + } 10771 + 10772 + out: 10773 + kfree(vmid_context); 10774 + lpfc_els_free_iocb(phba, icmdiocb); 10775 + lpfc_nlp_put(ndlp); 10776 + }