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

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
...@@ -3466,7 +3466,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) ...@@ -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 *) if ((phba->cfg_fof) && ((struct lpfc_device_data *)
scsi_cmnd->device->hostdata)->oas_enabled) 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; return 0;
} }
...@@ -3606,6 +3606,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, ...@@ -3606,6 +3606,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
*/ */
iocb_cmd->un.fcpi.fcpi_parm = fcpdl; 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; return 0;
err: err:
if (lpfc_cmd->seg_cnt) if (lpfc_cmd->seg_cnt)
...@@ -4876,6 +4884,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) ...@@ -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 */ /* ABTS WQE must go to the same WQ as the WQE to be aborted */
abtsiocb->fcp_wqidx = iocb->fcp_wqidx; abtsiocb->fcp_wqidx = iocb->fcp_wqidx;
abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; 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)) if (lpfc_is_link_up(phba))
icmd->ulpCommand = CMD_ABORT_XRI_CN; icmd->ulpCommand = CMD_ABORT_XRI_CN;
......
...@@ -8753,6 +8753,37 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) ...@@ -8753,6 +8753,37 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
return 0; 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 * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb
* @phba: Pointer to HBA context object. * @phba: Pointer to HBA context object.
...@@ -8778,28 +8809,17 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, ...@@ -8778,28 +8809,17 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
int rc, idx; int rc, idx;
if (phba->sli_rev == LPFC_SLI_REV4) { if (phba->sli_rev == LPFC_SLI_REV4) {
if (piocb->iocb_flag & LPFC_IO_FCP) { ring_number = lpfc_sli_calc_ring(phba, ring_number, piocb);
if (!phba->cfg_fof || (!(piocb->iocb_flag & if (unlikely(ring_number == LPFC_HBA_ERROR))
LPFC_IO_OAS))) {
if (unlikely(!phba->sli4_hba.fcp_wq))
return IOCB_ERROR; return IOCB_ERROR;
idx = lpfc_sli4_scmd_to_wqidx_distr(phba); idx = piocb->fcp_wqidx;
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;
}
pring = &phba->sli.ring[ring_number]; pring = &phba->sli.ring[ring_number];
spin_lock_irqsave(&pring->ring_lock, iflags); spin_lock_irqsave(&pring->ring_lock, iflags);
rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag);
flag);
spin_unlock_irqrestore(&pring->ring_lock, iflags); 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]; fcp_eq_hdl = &phba->sli4_hba.fcp_eq_hdl[idx];
if (atomic_dec_and_test(&fcp_eq_hdl-> if (atomic_dec_and_test(&fcp_eq_hdl->
...@@ -8826,14 +8846,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, ...@@ -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); 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 { } else {
/* For now, SLI2/3 will still use hbalock */ /* For now, SLI2/3 will still use hbalock */
spin_lock_irqsave(&phba->hbalock, iflags); spin_lock_irqsave(&phba->hbalock, iflags);
...@@ -9715,6 +9727,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -9715,6 +9727,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *abtsiocbp; struct lpfc_iocbq *abtsiocbp;
IOCB_t *icmd = NULL; IOCB_t *icmd = NULL;
IOCB_t *iabt = NULL; IOCB_t *iabt = NULL;
int ring_number;
int retval; int retval;
unsigned long iflags; unsigned long iflags;
...@@ -9755,6 +9768,8 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -9755,6 +9768,8 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx;
if (cmdiocb->iocb_flag & LPFC_IO_FCP) if (cmdiocb->iocb_flag & LPFC_IO_FCP)
abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; 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) if (phba->link_state >= LPFC_LINK_UP)
iabt->ulpCommand = CMD_ABORT_XRI_CN; iabt->ulpCommand = CMD_ABORT_XRI_CN;
...@@ -9771,6 +9786,11 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -9771,6 +9786,11 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
abtsiocbp->iotag); abtsiocbp->iotag);
if (phba->sli_rev == LPFC_SLI_REV4) { 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 */ /* Note: both hbalock and ring_lock need to be set here */
spin_lock_irqsave(&pring->ring_lock, iflags); spin_lock_irqsave(&pring->ring_lock, iflags);
retval = __lpfc_sli_issue_iocb(phba, pring->ringno, 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, ...@@ -10068,6 +10088,8 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; abtsiocb->fcp_wqidx = iocbq->fcp_wqidx;
if (iocbq->iocb_flag & LPFC_IO_FCP) if (iocbq->iocb_flag & LPFC_IO_FCP)
abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; 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)) if (lpfc_is_link_up(phba))
abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN;
...@@ -10167,6 +10189,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, ...@@ -10167,6 +10189,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx; abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx;
if (iocbq->iocb_flag & LPFC_IO_FCP) if (iocbq->iocb_flag & LPFC_IO_FCP)
abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; 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)) if (lpfc_is_link_up(phba))
abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN; abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN;
......
...@@ -79,6 +79,7 @@ struct lpfc_iocbq { ...@@ -79,6 +79,7 @@ struct lpfc_iocbq {
#define LPFC_FIP_ELS_ID_SHIFT 14 #define LPFC_FIP_ELS_ID_SHIFT 14
#define LPFC_IO_OAS 0x10000 /* OAS FCP IO */ #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 drvrTimeout; /* driver timeout in seconds */
uint32_t fcp_wqidx; /* index to FCP work queue */ uint32_t fcp_wqidx; /* index to FCP work queue */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment