Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bd2bff5 authored by James Smart's avatar James Smart Committed by Christoph Hellwig
Browse files

lpfc: fix locking issues with abort data paths



Fix locking issues with abort data paths

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarDick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 12838e74
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -3466,7 +3466,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
	 */
	if ((phba->cfg_fof) && ((struct lpfc_device_data *)
		scsi_cmnd->device->hostdata)->oas_enabled)
		lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_OAS;
		lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
	return 0;
}

@@ -3606,6 +3606,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
	 */
	iocb_cmd->un.fcpi.fcpi_parm = fcpdl;

	/*
	 * If the OAS driver feature is enabled and the lun is enabled for
	 * OAS, set the oas iocb related flags.
	 */
	if ((phba->cfg_fof) && ((struct lpfc_device_data *)
		scsi_cmnd->device->hostdata)->oas_enabled)
		lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);

	return 0;
err:
	if (lpfc_cmd->seg_cnt)
@@ -4876,6 +4884,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
	/* ABTS WQE must go to the same WQ as the WQE to be aborted */
	abtsiocb->fcp_wqidx = iocb->fcp_wqidx;
	abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
	if (iocb->iocb_flag & LPFC_IO_FOF)
		abtsiocb->iocb_flag |= LPFC_IO_FOF;

	if (lpfc_is_link_up(phba))
		icmd->ulpCommand = CMD_ABORT_XRI_CN;
+71 −47
Original line number Diff line number Diff line
@@ -8753,6 +8753,37 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
	return 0;
}
int
lpfc_sli_calc_ring(struct lpfc_hba *phba, uint32_t ring_number,
		    struct lpfc_iocbq *piocb)
{
	uint32_t idx;
	if (phba->sli_rev == LPFC_SLI_REV4) {
		if (piocb->iocb_flag &  (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) {
			/*
			 * fcp_wqidx should already be setup based on what
			 * completion queue we want to use.
			 */
			if (!(phba->cfg_fof) ||
			    (!(piocb->iocb_flag & LPFC_IO_FOF))) {
				if (unlikely(!phba->sli4_hba.fcp_wq))
					return LPFC_HBA_ERROR;
				idx = lpfc_sli4_scmd_to_wqidx_distr(phba);
				piocb->fcp_wqidx = idx;
				ring_number = MAX_SLI3_CONFIGURED_RINGS + idx;
			} else {
				if (unlikely(!phba->sli4_hba.oas_wq))
					return LPFC_HBA_ERROR;
				idx = 0;
				piocb->fcp_wqidx = idx;
				ring_number =  LPFC_FCP_OAS_RING;
			}
		}
	}
	return ring_number;
}
/**
 * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb
 * @phba: Pointer to HBA context object.
@@ -8778,28 +8809,17 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
	int rc, idx;
	if (phba->sli_rev == LPFC_SLI_REV4) {
		if (piocb->iocb_flag &  LPFC_IO_FCP) {
			if (!phba->cfg_fof || (!(piocb->iocb_flag &
				LPFC_IO_OAS))) {
				if (unlikely(!phba->sli4_hba.fcp_wq))
		ring_number = lpfc_sli_calc_ring(phba, ring_number, piocb);
		if (unlikely(ring_number == LPFC_HBA_ERROR))
			return IOCB_ERROR;
				idx = lpfc_sli4_scmd_to_wqidx_distr(phba);
				piocb->fcp_wqidx = idx;
				ring_number = MAX_SLI3_CONFIGURED_RINGS + idx;
			} else {
				if (unlikely(!phba->sli4_hba.oas_wq))
					return IOCB_ERROR;
				idx = 0;
				piocb->fcp_wqidx = 0;
				ring_number =  LPFC_FCP_OAS_RING;
			}
		idx = piocb->fcp_wqidx;
		pring = &phba->sli.ring[ring_number];
		spin_lock_irqsave(&pring->ring_lock, iflags);
			rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb,
				flag);
		rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag);
		spin_unlock_irqrestore(&pring->ring_lock, iflags);
			if (lpfc_fcp_look_ahead) {
		if (lpfc_fcp_look_ahead && (piocb->iocb_flag &  LPFC_IO_FCP)) {
			fcp_eq_hdl = &phba->sli4_hba.fcp_eq_hdl[idx];
			if (atomic_dec_and_test(&fcp_eq_hdl->
@@ -8826,14 +8846,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
			}
			atomic_inc(&fcp_eq_hdl->fcp_eq_in_use);
		}
		} else {
			pring = &phba->sli.ring[ring_number];
			spin_lock_irqsave(&pring->ring_lock, iflags);
			rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb,
				flag);
			spin_unlock_irqrestore(&pring->ring_lock, iflags);
		}
	} else {
		/* For now, SLI2/3 will still use hbalock */
		spin_lock_irqsave(&phba->hbalock, iflags);
@@ -9715,6 +9727,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	struct lpfc_iocbq *abtsiocbp;
	IOCB_t *icmd = NULL;
	IOCB_t *iabt = NULL;
	int ring_number;
	int retval;
	unsigned long iflags;
@@ -9755,6 +9768,8 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx;
	if (cmdiocb->iocb_flag & LPFC_IO_FCP)
		abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX;
	if (cmdiocb->iocb_flag & LPFC_IO_FOF)
		abtsiocbp->iocb_flag |= LPFC_IO_FOF;
	if (phba->link_state >= LPFC_LINK_UP)
		iabt->ulpCommand = CMD_ABORT_XRI_CN;
@@ -9771,6 +9786,11 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
			 abtsiocbp->iotag);
	if (phba->sli_rev == LPFC_SLI_REV4) {
		ring_number =
			lpfc_sli_calc_ring(phba, pring->ringno, abtsiocbp);
		if (unlikely(ring_number == LPFC_HBA_ERROR))
			return 0;
		pring = &phba->sli.ring[ring_number];
		/* Note: both hbalock and ring_lock need to be set here */
		spin_lock_irqsave(&pring->ring_lock, iflags);
		retval = __lpfc_sli_issue_iocb(phba, pring->ringno,
@@ -10068,6 +10088,8 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
		abtsiocb->fcp_wqidx = iocbq->fcp_wqidx;
		if (iocbq->iocb_flag & LPFC_IO_FCP)
			abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
		if (iocbq->iocb_flag & LPFC_IO_FOF)
			abtsiocb->iocb_flag |= LPFC_IO_FOF;
		if (lpfc_is_link_up(phba))
			abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
@@ -10167,6 +10189,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
		abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx;
		if (iocbq->iocb_flag & LPFC_IO_FCP)
			abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
		if (iocbq->iocb_flag & LPFC_IO_FOF)
			abtsiocbq->iocb_flag |= LPFC_IO_FOF;
		if (lpfc_is_link_up(phba))
			abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN;
+1 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ struct lpfc_iocbq {
#define LPFC_FIP_ELS_ID_SHIFT	14

#define LPFC_IO_OAS		0x10000 /* OAS FCP IO */
#define LPFC_IO_FOF		0x20000 /* FOF FCP IO */

	uint32_t drvrTimeout;	/* driver timeout in seconds */
	uint32_t fcp_wqidx;	/* index to FCP work queue */