scsi: lpfc: Support loopback tests with VMID enabled

The VMID feature adds an extra application services header to each frame.
As such, the loopback test path is updated to accommodate the extra
application header.

Changes include filling in APPID and WQES bit fields for XMIT_SEQUENCE64
commands, a special loopback source APPID for verifying received loopback
data matches what is sent, and increasing ELS WQ size to accommodate the
APPID field in loopback test mode.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240912232447.45607-8-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by Justin Tee and committed by Martin K. Petersen eeb85c65 1af9af1f

+70 -4
+3
drivers/scsi/lpfc/lpfc_bsg.c
··· 3208 cmdiocbq->num_bdes = num_bde; 3209 cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; 3210 cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK; 3211 cmdiocbq->vport = phba->pport; 3212 cmdiocbq->cmd_cmpl = NULL; 3213 cmdiocbq->bpl_dmabuf = txbmp;
··· 3208 cmdiocbq->num_bdes = num_bde; 3209 cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC; 3210 cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK; 3211 + if (phba->cfg_vmid_app_header) 3212 + cmdiocbq->cmd_flag |= LPFC_IO_VMID; 3213 + 3214 cmdiocbq->vport = phba->pport; 3215 cmdiocbq->cmd_cmpl = NULL; 3216 cmdiocbq->bpl_dmabuf = txbmp;
+21
drivers/scsi/lpfc/lpfc_hw.h
··· 562 #include <uapi/scsi/fc/fc_els.h> 563 564 /* 565 * Extended Link Service LS_COMMAND codes (Payload Word 0) 566 */ 567 #ifdef __BIG_ENDIAN_BITFIELD
··· 562 #include <uapi/scsi/fc/fc_els.h> 563 564 /* 565 + * Application Header 566 + */ 567 + struct fc_app_header { 568 + uint32_t dst_app_id; 569 + uint32_t src_app_id; 570 + #define LOOPBACK_SRC_APPID 0x4321 571 + uint32_t word2; 572 + uint32_t word3; 573 + }; 574 + 575 + /* 576 + * dfctl optional header definition 577 + */ 578 + enum lpfc_fc_dfctl { 579 + LPFC_FC_NO_DEVICE_HEADER, 580 + LPFC_FC_16B_DEVICE_HEADER, 581 + LPFC_FC_32B_DEVICE_HEADER, 582 + LPFC_FC_64B_DEVICE_HEADER, 583 + }; 584 + 585 + /* 586 * Extended Link Service LS_COMMAND codes (Payload Word 0) 587 */ 588 #ifdef __BIG_ENDIAN_BITFIELD
+9 -2
drivers/scsi/lpfc/lpfc_init.c
··· 10451 struct lpfc_vector_map_info *cpup; 10452 struct lpfc_vector_map_info *eqcpup; 10453 struct lpfc_eq_intr_info *eqi; 10454 10455 /* 10456 * Create HBA Record arrays. ··· 10671 * Create ELS Work Queues 10672 */ 10673 10674 - /* Create slow-path ELS Work Queue */ 10675 qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE, 10676 - phba->sli4_hba.wq_esize, 10677 phba->sli4_hba.wq_ecount, cpu); 10678 if (!qdesc) { 10679 lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
··· 10451 struct lpfc_vector_map_info *cpup; 10452 struct lpfc_vector_map_info *eqcpup; 10453 struct lpfc_eq_intr_info *eqi; 10454 + u32 wqesize; 10455 10456 /* 10457 * Create HBA Record arrays. ··· 10670 * Create ELS Work Queues 10671 */ 10672 10673 + /* 10674 + * Create slow-path ELS Work Queue. 10675 + * Increase the ELS WQ size when WQEs contain an embedded cdb 10676 + */ 10677 + wqesize = (phba->fcp_embed_io) ? 10678 + LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize; 10679 + 10680 qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE, 10681 + wqesize, 10682 phba->sli4_hba.wq_ecount, cpu); 10683 if (!qdesc) { 10684 lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+37 -2
drivers/scsi/lpfc/lpfc_sli.c
··· 11093 /* Word 9 */ 11094 bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, ox_id); 11095 11096 - /* Word 12 */ 11097 - if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK)) 11098 wqe->xmit_sequence.xmit_len = full_size; 11099 else 11100 wqe->xmit_sequence.xmit_len = 11101 wqe->xmit_sequence.bde.tus.f.bdeSize; ··· 18442 { 18443 /* make rctl_names static to save stack space */ 18444 struct fc_vft_header *fc_vft_hdr; 18445 uint32_t *header = (uint32_t *) fc_hdr; 18446 18447 #define FC_RCTL_MDS_DIAGS 0xF4 ··· 18496 case FC_TYPE_ILS: 18497 default: 18498 goto drop; 18499 } 18500 18501 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
··· 11093 /* Word 9 */ 11094 bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, ox_id); 11095 11096 + if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK)) { 11097 + /* Word 10 */ 11098 + if (cmdiocbq->cmd_flag & LPFC_IO_VMID) { 11099 + bf_set(wqe_appid, &wqe->xmit_sequence.wqe_com, 1); 11100 + bf_set(wqe_wqes, &wqe->xmit_sequence.wqe_com, 1); 11101 + wqe->words[31] = LOOPBACK_SRC_APPID; 11102 + } 11103 + 11104 + /* Word 12 */ 11105 wqe->xmit_sequence.xmit_len = full_size; 11106 + } 11107 else 11108 wqe->xmit_sequence.xmit_len = 11109 wqe->xmit_sequence.bde.tus.f.bdeSize; ··· 18434 { 18435 /* make rctl_names static to save stack space */ 18436 struct fc_vft_header *fc_vft_hdr; 18437 + struct fc_app_header *fc_app_hdr; 18438 uint32_t *header = (uint32_t *) fc_hdr; 18439 18440 #define FC_RCTL_MDS_DIAGS 0xF4 ··· 18487 case FC_TYPE_ILS: 18488 default: 18489 goto drop; 18490 + } 18491 + 18492 + if (unlikely(phba->link_flag == LS_LOOPBACK_MODE && 18493 + phba->cfg_vmid_app_header)) { 18494 + /* Application header is 16B device header */ 18495 + if (fc_hdr->fh_df_ctl & LPFC_FC_16B_DEVICE_HEADER) { 18496 + fc_app_hdr = (struct fc_app_header *) (fc_hdr + 1); 18497 + if (be32_to_cpu(fc_app_hdr->src_app_id) != 18498 + LOOPBACK_SRC_APPID) { 18499 + lpfc_printf_log(phba, KERN_WARNING, 18500 + LOG_ELS | LOG_LIBDFC, 18501 + "1932 Loopback src app id " 18502 + "not matched, app_id:x%x\n", 18503 + be32_to_cpu(fc_app_hdr->src_app_id)); 18504 + 18505 + goto drop; 18506 + } 18507 + } else { 18508 + lpfc_printf_log(phba, KERN_WARNING, 18509 + LOG_ELS | LOG_LIBDFC, 18510 + "1933 Loopback df_ctl bit not set, " 18511 + "df_ctl:x%x\n", 18512 + fc_hdr->fh_df_ctl); 18513 + 18514 + goto drop; 18515 + } 18516 } 18517 18518 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,