scsi: lpfc: Correct MDS loopback diagnostics support

The existing MDS loopback diagnostics support processing received frames in
the slowpath work thread. It caps the number of frames it will process at
64, before waiting for another event to indicate additional frame
reception. The net-net is this results in very slow frame processing during
loopback tests and sometimes orphans an io, causing the loopback test to
report failure by the switch.

Move MDS loopback frame processing out of the slow path worker thread and
into the normal RQ processing routines.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
James Smart 2018-12-13 15:17:53 -08:00 committed by Martin K. Petersen
parent 2977a09512
commit e817e5d703
1 changed files with 34 additions and 15 deletions

View File

@ -13487,6 +13487,8 @@ lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba,
return workposted;
}
#define FC_RCTL_MDS_DIAGS 0xF4
/**
* lpfc_sli4_sp_handle_rcqe - Process a receive-queue completion queue entry
* @phba: Pointer to HBA context object.
@ -13500,6 +13502,7 @@ static bool
lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
{
bool workposted = false;
struct fc_frame_header *fc_hdr;
struct lpfc_queue *hrq = phba->sli4_hba.hdr_rq;
struct lpfc_queue *drq = phba->sli4_hba.dat_rq;
struct lpfc_nvmet_tgtport *tgtp;
@ -13536,7 +13539,17 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
hrq->RQ_buf_posted--;
memcpy(&dma_buf->cq_event.cqe.rcqe_cmpl, rcqe, sizeof(*rcqe));
/* save off the frame for the word thread to process */
fc_hdr = (struct fc_frame_header *)dma_buf->hbuf.virt;
if (fc_hdr->fh_r_ctl == FC_RCTL_MDS_DIAGS ||
fc_hdr->fh_r_ctl == FC_RCTL_DD_UNSOL_DATA) {
spin_unlock_irqrestore(&phba->hbalock, iflags);
/* Handle MDS Loopback frames */
lpfc_sli4_handle_mds_loopback(phba->pport, dma_buf);
break;
}
/* save off the frame for the work thread to process */
list_add_tail(&dma_buf->cq_event.list,
&phba->sli4_hba.sp_queue_event);
/* Frame received */
@ -16940,8 +16953,6 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
struct fc_vft_header *fc_vft_hdr;
uint32_t *header = (uint32_t *) fc_hdr;
#define FC_RCTL_MDS_DIAGS 0xF4
switch (fc_hdr->fh_r_ctl) {
case FC_RCTL_DD_UNCAT: /* uncategorized information */
case FC_RCTL_DD_SOL_DATA: /* solicited data */
@ -16980,15 +16991,12 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
goto drop;
}
#define FC_TYPE_VENDOR_UNIQUE 0xFF
switch (fc_hdr->fh_type) {
case FC_TYPE_BLS:
case FC_TYPE_ELS:
case FC_TYPE_FCP:
case FC_TYPE_CT:
case FC_TYPE_NVME:
case FC_TYPE_VENDOR_UNIQUE:
break;
case FC_TYPE_IP:
case FC_TYPE_ILS:
@ -17818,6 +17826,7 @@ lpfc_sli4_mds_loopback_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
dma_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
kfree(pcmd);
lpfc_sli_release_iocbq(phba, cmdiocb);
lpfc_drain_txq(phba);
}
static void
@ -17831,14 +17840,23 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
struct lpfc_dmabuf *pcmd = NULL;
uint32_t frame_len;
int rc;
unsigned long iflags;
fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
frame_len = bf_get(lpfc_rcqe_length, &dmabuf->cq_event.cqe.rcqe_cmpl);
/* Send the received frame back */
iocbq = lpfc_sli_get_iocbq(phba);
if (!iocbq)
goto exit;
if (!iocbq) {
/* Queue cq event and wakeup worker thread to process it */
spin_lock_irqsave(&phba->hbalock, iflags);
list_add_tail(&dmabuf->cq_event.list,
&phba->sli4_hba.sp_queue_event);
phba->hba_flag |= HBA_SP_QUEUE_EVT;
spin_unlock_irqrestore(&phba->hbalock, iflags);
lpfc_worker_wake_up(phba);
return;
}
/* Allocate buffer for command payload */
pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
@ -17923,6 +17941,14 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
/* Process each received buffer */
fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
if (fc_hdr->fh_r_ctl == FC_RCTL_MDS_DIAGS ||
fc_hdr->fh_r_ctl == FC_RCTL_DD_UNSOL_DATA) {
vport = phba->pport;
/* Handle MDS Loopback frames */
lpfc_sli4_handle_mds_loopback(vport, dmabuf);
return;
}
/* check to see if this a valid type of frame */
if (lpfc_fc_frame_check(phba, fc_hdr)) {
lpfc_in_buf_free(phba, &dmabuf->dbuf);
@ -17937,13 +17963,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
fcfi = bf_get(lpfc_rcqe_fcf_id,
&dmabuf->cq_event.cqe.rcqe_cmpl);
if (fc_hdr->fh_r_ctl == 0xF4 && fc_hdr->fh_type == 0xFF) {
vport = phba->pport;
/* Handle MDS Loopback frames */
lpfc_sli4_handle_mds_loopback(vport, dmabuf);
return;
}
/* d_id this frame is directed to */
did = sli4_did_from_fc_hdr(fc_hdr);