diff options
| author | James Smart <james.smart@emulex.com> | 2014-09-03 12:57:30 -0400 |
|---|---|---|
| committer | Christoph Hellwig <hch@lst.de> | 2014-09-16 12:10:11 -0400 |
| commit | 9bd2bff5e7140beab948ad3934f4039246748a24 (patch) | |
| tree | e949fa522286924bf3b580f3745bc992d4fac5fc /drivers/scsi/lpfc | |
| parent | 12838e74f5164054fd7d5f5201a846ebb9755471 (diff) | |
lpfc: fix locking issues with abort data paths
Fix locking issues with abort data paths
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: Dick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/lpfc')
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 12 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 118 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 |
3 files changed, 83 insertions, 48 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 6094545883a3..0f6be8560508 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -3466,7 +3466,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 3466 | */ | 3466 | */ |
| 3467 | if ((phba->cfg_fof) && ((struct lpfc_device_data *) | 3467 | if ((phba->cfg_fof) && ((struct lpfc_device_data *) |
| 3468 | scsi_cmnd->device->hostdata)->oas_enabled) | 3468 | scsi_cmnd->device->hostdata)->oas_enabled) |
| 3469 | lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_OAS; | 3469 | lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); |
| 3470 | return 0; | 3470 | return 0; |
| 3471 | } | 3471 | } |
| 3472 | 3472 | ||
| @@ -3606,6 +3606,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
| 3606 | */ | 3606 | */ |
| 3607 | iocb_cmd->un.fcpi.fcpi_parm = fcpdl; | 3607 | iocb_cmd->un.fcpi.fcpi_parm = fcpdl; |
| 3608 | 3608 | ||
| 3609 | /* | ||
| 3610 | * If the OAS driver feature is enabled and the lun is enabled for | ||
| 3611 | * OAS, set the oas iocb related flags. | ||
| 3612 | */ | ||
| 3613 | if ((phba->cfg_fof) && ((struct lpfc_device_data *) | ||
| 3614 | scsi_cmnd->device->hostdata)->oas_enabled) | ||
| 3615 | lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); | ||
| 3616 | |||
| 3609 | return 0; | 3617 | return 0; |
| 3610 | err: | 3618 | err: |
| 3611 | if (lpfc_cmd->seg_cnt) | 3619 | if (lpfc_cmd->seg_cnt) |
| @@ -4876,6 +4884,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
| 4876 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | 4884 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ |
| 4877 | abtsiocb->fcp_wqidx = iocb->fcp_wqidx; | 4885 | abtsiocb->fcp_wqidx = iocb->fcp_wqidx; |
| 4878 | abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; | 4886 | abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; |
| 4887 | if (iocb->iocb_flag & LPFC_IO_FOF) | ||
| 4888 | abtsiocb->iocb_flag |= LPFC_IO_FOF; | ||
| 4879 | 4889 | ||
| 4880 | if (lpfc_is_link_up(phba)) | 4890 | if (lpfc_is_link_up(phba)) |
| 4881 | icmd->ulpCommand = CMD_ABORT_XRI_CN; | 4891 | icmd->ulpCommand = CMD_ABORT_XRI_CN; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index deb7f126a2f1..7185aac24324 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -8753,6 +8753,37 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) | |||
| 8753 | return 0; | 8753 | return 0; |
| 8754 | } | 8754 | } |
| 8755 | 8755 | ||
| 8756 | int | ||
| 8757 | lpfc_sli_calc_ring(struct lpfc_hba *phba, uint32_t ring_number, | ||
| 8758 | struct lpfc_iocbq *piocb) | ||
| 8759 | { | ||
| 8760 | uint32_t idx; | ||
| 8761 | |||
| 8762 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
| 8763 | if (piocb->iocb_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) { | ||
| 8764 | /* | ||
| 8765 | * fcp_wqidx should already be setup based on what | ||
| 8766 | * completion queue we want to use. | ||
| 8767 | */ | ||
| 8768 | if (!(phba->cfg_fof) || | ||
| 8769 | (!(piocb->iocb_flag & LPFC_IO_FOF))) { | ||
| 8770 | if (unlikely(!phba->sli4_hba.fcp_wq)) | ||
| 8771 | return LPFC_HBA_ERROR; | ||
| 8772 | idx = lpfc_sli4_scmd_to_wqidx_distr(phba); | ||
| 8773 | piocb->fcp_wqidx = idx; | ||
| 8774 | ring_number = MAX_SLI3_CONFIGURED_RINGS + idx; | ||
| 8775 | } else { | ||
| 8776 | if (unlikely(!phba->sli4_hba.oas_wq)) | ||
| 8777 | return LPFC_HBA_ERROR; | ||
| 8778 | idx = 0; | ||
| 8779 | piocb->fcp_wqidx = idx; | ||
| 8780 | ring_number = LPFC_FCP_OAS_RING; | ||
| 8781 | } | ||
| 8782 | } | ||
| 8783 | } | ||
| 8784 | return ring_number; | ||
| 8785 | } | ||
| 8786 | |||
| 8756 | /** | 8787 | /** |
| 8757 | * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb | 8788 | * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb |
| 8758 | * @phba: Pointer to HBA context object. | 8789 | * @phba: Pointer to HBA context object. |
| @@ -8778,61 +8809,42 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, | |||
| 8778 | int rc, idx; | 8809 | int rc, idx; |
| 8779 | 8810 | ||
| 8780 | if (phba->sli_rev == LPFC_SLI_REV4) { | 8811 | if (phba->sli_rev == LPFC_SLI_REV4) { |
| 8781 | if (piocb->iocb_flag & LPFC_IO_FCP) { | 8812 | ring_number = lpfc_sli_calc_ring(phba, ring_number, piocb); |
| 8782 | if (!phba->cfg_fof || (!(piocb->iocb_flag & | 8813 | if (unlikely(ring_number == LPFC_HBA_ERROR)) |
| 8783 | LPFC_IO_OAS))) { | 8814 | return IOCB_ERROR; |
| 8784 | if (unlikely(!phba->sli4_hba.fcp_wq)) | 8815 | idx = piocb->fcp_wqidx; |
| 8785 | return IOCB_ERROR; | ||
| 8786 | idx = lpfc_sli4_scmd_to_wqidx_distr(phba); | ||
| 8787 | piocb->fcp_wqidx = idx; | ||
| 8788 | ring_number = MAX_SLI3_CONFIGURED_RINGS + idx; | ||
| 8789 | } else { | ||
| 8790 | if (unlikely(!phba->sli4_hba.oas_wq)) | ||
| 8791 | return IOCB_ERROR; | ||
| 8792 | idx = 0; | ||
| 8793 | piocb->fcp_wqidx = 0; | ||
| 8794 | ring_number = LPFC_FCP_OAS_RING; | ||
| 8795 | } | ||
| 8796 | pring = &phba->sli.ring[ring_number]; | ||
| 8797 | spin_lock_irqsave(&pring->ring_lock, iflags); | ||
| 8798 | rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, | ||
| 8799 | flag); | ||
| 8800 | spin_unlock_irqrestore(&pring->ring_lock, iflags); | ||
| 8801 | 8816 | ||
| 8802 | if (lpfc_fcp_look_ahead) { | 8817 | pring = &phba->sli.ring[ring_number]; |
| 8803 | fcp_eq_hdl = &phba->sli4_hba.fcp_eq_hdl[idx]; | 8818 | spin_lock_irqsave(&pring->ring_lock, iflags); |
| 8819 | rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); | ||
| 8820 | spin_unlock_irqrestore(&pring->ring_lock, iflags); | ||
| 8804 | 8821 | ||
| 8805 | if (atomic_dec_and_test(&fcp_eq_hdl-> | 8822 | if (lpfc_fcp_look_ahead && (piocb->iocb_flag & LPFC_IO_FCP)) { |
| 8806 | fcp_eq_in_use)) { | 8823 | fcp_eq_hdl = &phba->sli4_hba.fcp_eq_hdl[idx]; |
| 8807 | 8824 | ||
| 8808 | /* Get associated EQ with this index */ | 8825 | if (atomic_dec_and_test(&fcp_eq_hdl-> |
| 8809 | fpeq = phba->sli4_hba.hba_eq[idx]; | 8826 | fcp_eq_in_use)) { |
| 8810 | 8827 | ||
| 8811 | /* Turn off interrupts from this EQ */ | 8828 | /* Get associated EQ with this index */ |
| 8812 | lpfc_sli4_eq_clr_intr(fpeq); | 8829 | fpeq = phba->sli4_hba.hba_eq[idx]; |
| 8813 | 8830 | ||
| 8814 | /* | 8831 | /* Turn off interrupts from this EQ */ |
| 8815 | * Process all the events on FCP EQ | 8832 | lpfc_sli4_eq_clr_intr(fpeq); |
| 8816 | */ | ||
| 8817 | while ((eqe = lpfc_sli4_eq_get(fpeq))) { | ||
| 8818 | lpfc_sli4_hba_handle_eqe(phba, | ||
| 8819 | eqe, idx); | ||
| 8820 | fpeq->EQ_processed++; | ||
| 8821 | } | ||
| 8822 | 8833 | ||
| 8823 | /* Always clear and re-arm the EQ */ | 8834 | /* |
| 8824 | lpfc_sli4_eq_release(fpeq, | 8835 | * Process all the events on FCP EQ |
| 8825 | LPFC_QUEUE_REARM); | 8836 | */ |
| 8837 | while ((eqe = lpfc_sli4_eq_get(fpeq))) { | ||
| 8838 | lpfc_sli4_hba_handle_eqe(phba, | ||
| 8839 | eqe, idx); | ||
| 8840 | fpeq->EQ_processed++; | ||
| 8826 | } | 8841 | } |
| 8827 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
| 8828 | } | ||
| 8829 | } else { | ||
| 8830 | pring = &phba->sli.ring[ring_number]; | ||
| 8831 | spin_lock_irqsave(&pring->ring_lock, iflags); | ||
| 8832 | rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, | ||
| 8833 | flag); | ||
| 8834 | spin_unlock_irqrestore(&pring->ring_lock, iflags); | ||
| 8835 | 8842 | ||
| 8843 | /* Always clear and re-arm the EQ */ | ||
| 8844 | lpfc_sli4_eq_release(fpeq, | ||
| 8845 | LPFC_QUEUE_REARM); | ||
| 8846 | } | ||
| 8847 | atomic_inc(&fcp_eq_hdl->fcp_eq_in_use); | ||
| 8836 | } | 8848 | } |
| 8837 | } else { | 8849 | } else { |
| 8838 | /* For now, SLI2/3 will still use hbalock */ | 8850 | /* For now, SLI2/3 will still use hbalock */ |
| @@ -9715,6 +9727,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 9715 | struct lpfc_iocbq *abtsiocbp; | 9727 | struct lpfc_iocbq *abtsiocbp; |
| 9716 | IOCB_t *icmd = NULL; | 9728 | IOCB_t *icmd = NULL; |
| 9717 | IOCB_t *iabt = NULL; | 9729 | IOCB_t *iabt = NULL; |
| 9730 | int ring_number; | ||
| 9718 | int retval; | 9731 | int retval; |
| 9719 | unsigned long iflags; | 9732 | unsigned long iflags; |
| 9720 | 9733 | ||
| @@ -9755,6 +9768,8 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 9755 | abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; | 9768 | abtsiocbp->fcp_wqidx = cmdiocb->fcp_wqidx; |
| 9756 | if (cmdiocb->iocb_flag & LPFC_IO_FCP) | 9769 | if (cmdiocb->iocb_flag & LPFC_IO_FCP) |
| 9757 | abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; | 9770 | abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; |
| 9771 | if (cmdiocb->iocb_flag & LPFC_IO_FOF) | ||
| 9772 | abtsiocbp->iocb_flag |= LPFC_IO_FOF; | ||
| 9758 | 9773 | ||
| 9759 | if (phba->link_state >= LPFC_LINK_UP) | 9774 | if (phba->link_state >= LPFC_LINK_UP) |
| 9760 | iabt->ulpCommand = CMD_ABORT_XRI_CN; | 9775 | 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 | abtsiocbp->iotag); | 9786 | abtsiocbp->iotag); |
| 9772 | 9787 | ||
| 9773 | if (phba->sli_rev == LPFC_SLI_REV4) { | 9788 | if (phba->sli_rev == LPFC_SLI_REV4) { |
| 9789 | ring_number = | ||
| 9790 | lpfc_sli_calc_ring(phba, pring->ringno, abtsiocbp); | ||
| 9791 | if (unlikely(ring_number == LPFC_HBA_ERROR)) | ||
| 9792 | return 0; | ||
| 9793 | pring = &phba->sli.ring[ring_number]; | ||
| 9774 | /* Note: both hbalock and ring_lock need to be set here */ | 9794 | /* Note: both hbalock and ring_lock need to be set here */ |
| 9775 | spin_lock_irqsave(&pring->ring_lock, iflags); | 9795 | spin_lock_irqsave(&pring->ring_lock, iflags); |
| 9776 | retval = __lpfc_sli_issue_iocb(phba, pring->ringno, | 9796 | 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 | abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; | 10088 | abtsiocb->fcp_wqidx = iocbq->fcp_wqidx; |
| 10069 | if (iocbq->iocb_flag & LPFC_IO_FCP) | 10089 | if (iocbq->iocb_flag & LPFC_IO_FCP) |
| 10070 | abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; | 10090 | abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; |
| 10091 | if (iocbq->iocb_flag & LPFC_IO_FOF) | ||
| 10092 | abtsiocb->iocb_flag |= LPFC_IO_FOF; | ||
| 10071 | 10093 | ||
| 10072 | if (lpfc_is_link_up(phba)) | 10094 | if (lpfc_is_link_up(phba)) |
| 10073 | abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; | 10095 | 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 | abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx; | 10189 | abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx; |
| 10168 | if (iocbq->iocb_flag & LPFC_IO_FCP) | 10190 | if (iocbq->iocb_flag & LPFC_IO_FCP) |
| 10169 | abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; | 10191 | abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; |
| 10192 | if (iocbq->iocb_flag & LPFC_IO_FOF) | ||
| 10193 | abtsiocbq->iocb_flag |= LPFC_IO_FOF; | ||
| 10170 | 10194 | ||
| 10171 | if (lpfc_is_link_up(phba)) | 10195 | if (lpfc_is_link_up(phba)) |
| 10172 | abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN; | 10196 | abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index edb48832c39b..4a01452415cf 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
| @@ -79,6 +79,7 @@ struct lpfc_iocbq { | |||
| 79 | #define LPFC_FIP_ELS_ID_SHIFT 14 | 79 | #define LPFC_FIP_ELS_ID_SHIFT 14 |
| 80 | 80 | ||
| 81 | #define LPFC_IO_OAS 0x10000 /* OAS FCP IO */ | 81 | #define LPFC_IO_OAS 0x10000 /* OAS FCP IO */ |
| 82 | #define LPFC_IO_FOF 0x20000 /* FOF FCP IO */ | ||
| 82 | 83 | ||
| 83 | uint32_t drvrTimeout; /* driver timeout in seconds */ | 84 | uint32_t drvrTimeout; /* driver timeout in seconds */ |
| 84 | uint32_t fcp_wqidx; /* index to FCP work queue */ | 85 | uint32_t fcp_wqidx; /* index to FCP work queue */ |
