diff options
author | James Smart <james.smart@emulex.com> | 2014-04-04 13:52:31 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-06-02 12:29:01 -0400 |
commit | 98912dda4d287a7bc6f0b7a91cceb0fedd1492f6 (patch) | |
tree | e07fe118abc3c93d608bb5ae183f6cac483d20a3 /drivers/scsi/lpfc | |
parent | f38fa0bb7c4a54dc7eff622adc6fa7cf763d834d (diff) |
lpfc: Fixed locking for scsi task management commands
Fixed locking for scsi task management commands.
Signed-off-by: James Smart <james.smart@emulex.com>
Reviewed-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_crtn.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 25 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 118 |
3 files changed, 141 insertions, 5 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 429116a9cb7d..7d4271d0be8f 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -311,6 +311,9 @@ int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, | |||
311 | int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd); | 311 | int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd); |
312 | int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, | 312 | int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, |
313 | uint64_t, lpfc_ctx_cmd); | 313 | uint64_t, lpfc_ctx_cmd); |
314 | int | ||
315 | lpfc_sli_abort_taskmgmt(struct lpfc_vport *, struct lpfc_sli_ring *, | ||
316 | uint16_t, uint64_t, lpfc_ctx_cmd); | ||
314 | 317 | ||
315 | void lpfc_mbox_timeout(unsigned long); | 318 | void lpfc_mbox_timeout(unsigned long); |
316 | void lpfc_mbox_timeout_handler(struct lpfc_hba *); | 319 | void lpfc_mbox_timeout_handler(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 7d0f2951ca52..aa7fbdbf4e6c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -4783,7 +4783,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
4783 | struct lpfc_scsi_buf *lpfc_cmd; | 4783 | struct lpfc_scsi_buf *lpfc_cmd; |
4784 | IOCB_t *cmd, *icmd; | 4784 | IOCB_t *cmd, *icmd; |
4785 | int ret = SUCCESS, status = 0; | 4785 | int ret = SUCCESS, status = 0; |
4786 | unsigned long flags; | 4786 | struct lpfc_sli_ring *pring_s4; |
4787 | int ring_number, ret_val; | ||
4788 | unsigned long flags, iflags; | ||
4787 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); | 4789 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); |
4788 | 4790 | ||
4789 | status = fc_block_scsi_eh(cmnd); | 4791 | status = fc_block_scsi_eh(cmnd); |
@@ -4880,11 +4882,23 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
4880 | 4882 | ||
4881 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; | 4883 | abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; |
4882 | abtsiocb->vport = vport; | 4884 | abtsiocb->vport = vport; |
4885 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
4886 | ring_number = MAX_SLI3_CONFIGURED_RINGS + iocb->fcp_wqidx; | ||
4887 | pring_s4 = &phba->sli.ring[ring_number]; | ||
4888 | /* Note: both hbalock and ring_lock must be set here */ | ||
4889 | spin_lock_irqsave(&pring_s4->ring_lock, iflags); | ||
4890 | ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, | ||
4891 | abtsiocb, 0); | ||
4892 | spin_unlock_irqrestore(&pring_s4->ring_lock, iflags); | ||
4893 | } else { | ||
4894 | ret_val = __lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, | ||
4895 | abtsiocb, 0); | ||
4896 | } | ||
4883 | /* no longer need the lock after this point */ | 4897 | /* no longer need the lock after this point */ |
4884 | spin_unlock_irqrestore(&phba->hbalock, flags); | 4898 | spin_unlock_irqrestore(&phba->hbalock, flags); |
4885 | 4899 | ||
4886 | if (lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, abtsiocb, 0) == | 4900 | |
4887 | IOCB_ERROR) { | 4901 | if (ret_val == IOCB_ERROR) { |
4888 | lpfc_sli_release_iocbq(phba, abtsiocb); | 4902 | lpfc_sli_release_iocbq(phba, abtsiocb); |
4889 | ret = FAILED; | 4903 | ret = FAILED; |
4890 | goto out; | 4904 | goto out; |
@@ -5185,8 +5199,9 @@ lpfc_reset_flush_io_context(struct lpfc_vport *vport, uint16_t tgt_id, | |||
5185 | 5199 | ||
5186 | cnt = lpfc_sli_sum_iocb(vport, tgt_id, lun_id, context); | 5200 | cnt = lpfc_sli_sum_iocb(vport, tgt_id, lun_id, context); |
5187 | if (cnt) | 5201 | if (cnt) |
5188 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], | 5202 | lpfc_sli_abort_taskmgmt(vport, |
5189 | tgt_id, lun_id, context); | 5203 | &phba->sli.ring[phba->sli.fcp_ring], |
5204 | tgt_id, lun_id, context); | ||
5190 | later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies; | 5205 | later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies; |
5191 | while (time_after(later, jiffies) && cnt) { | 5206 | while (time_after(later, jiffies) && cnt) { |
5192 | schedule_timeout_uninterruptible(msecs_to_jiffies(20)); | 5207 | schedule_timeout_uninterruptible(msecs_to_jiffies(20)); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8791312e5977..34ba7aaec48c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -10118,6 +10118,124 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, | |||
10118 | } | 10118 | } |
10119 | 10119 | ||
10120 | /** | 10120 | /** |
10121 | * lpfc_sli_abort_taskmgmt - issue abort for all commands on a host/target/LUN | ||
10122 | * @vport: Pointer to virtual port. | ||
10123 | * @pring: Pointer to driver SLI ring object. | ||
10124 | * @tgt_id: SCSI ID of the target. | ||
10125 | * @lun_id: LUN ID of the scsi device. | ||
10126 | * @taskmgmt_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST. | ||
10127 | * | ||
10128 | * This function sends an abort command for every SCSI command | ||
10129 | * associated with the given virtual port pending on the ring | ||
10130 | * filtered by lpfc_sli_validate_fcp_iocb function. | ||
10131 | * When taskmgmt_cmd == LPFC_CTX_LUN, the function sends abort only to the | ||
10132 | * FCP iocbs associated with lun specified by tgt_id and lun_id | ||
10133 | * parameters | ||
10134 | * When taskmgmt_cmd == LPFC_CTX_TGT, the function sends abort only to the | ||
10135 | * FCP iocbs associated with SCSI target specified by tgt_id parameter. | ||
10136 | * When taskmgmt_cmd == LPFC_CTX_HOST, the function sends abort to all | ||
10137 | * FCP iocbs associated with virtual port. | ||
10138 | * This function returns number of iocbs it aborted . | ||
10139 | * This function is called with no locks held right after a taskmgmt | ||
10140 | * command is sent. | ||
10141 | **/ | ||
10142 | int | ||
10143 | lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, | ||
10144 | uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd cmd) | ||
10145 | { | ||
10146 | struct lpfc_hba *phba = vport->phba; | ||
10147 | struct lpfc_iocbq *abtsiocbq; | ||
10148 | struct lpfc_iocbq *iocbq; | ||
10149 | IOCB_t *icmd; | ||
10150 | int sum, i, ret_val; | ||
10151 | unsigned long iflags; | ||
10152 | struct lpfc_sli_ring *pring_s4; | ||
10153 | uint32_t ring_number; | ||
10154 | |||
10155 | spin_lock_irq(&phba->hbalock); | ||
10156 | |||
10157 | /* all I/Os are in process of being flushed */ | ||
10158 | if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) { | ||
10159 | spin_unlock_irq(&phba->hbalock); | ||
10160 | return 0; | ||
10161 | } | ||
10162 | sum = 0; | ||
10163 | |||
10164 | for (i = 1; i <= phba->sli.last_iotag; i++) { | ||
10165 | iocbq = phba->sli.iocbq_lookup[i]; | ||
10166 | |||
10167 | if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, | ||
10168 | cmd) != 0) | ||
10169 | continue; | ||
10170 | |||
10171 | /* | ||
10172 | * If the iocbq is already being aborted, don't take a second | ||
10173 | * action, but do count it. | ||
10174 | */ | ||
10175 | if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) | ||
10176 | continue; | ||
10177 | |||
10178 | /* issue ABTS for this IOCB based on iotag */ | ||
10179 | abtsiocbq = __lpfc_sli_get_iocbq(phba); | ||
10180 | if (abtsiocbq == NULL) | ||
10181 | continue; | ||
10182 | |||
10183 | icmd = &iocbq->iocb; | ||
10184 | abtsiocbq->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; | ||
10185 | abtsiocbq->iocb.un.acxri.abortContextTag = icmd->ulpContext; | ||
10186 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
10187 | abtsiocbq->iocb.un.acxri.abortIoTag = | ||
10188 | iocbq->sli4_xritag; | ||
10189 | else | ||
10190 | abtsiocbq->iocb.un.acxri.abortIoTag = icmd->ulpIoTag; | ||
10191 | abtsiocbq->iocb.ulpLe = 1; | ||
10192 | abtsiocbq->iocb.ulpClass = icmd->ulpClass; | ||
10193 | abtsiocbq->vport = vport; | ||
10194 | |||
10195 | /* ABTS WQE must go to the same WQ as the WQE to be aborted */ | ||
10196 | abtsiocbq->fcp_wqidx = iocbq->fcp_wqidx; | ||
10197 | if (iocbq->iocb_flag & LPFC_IO_FCP) | ||
10198 | abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX; | ||
10199 | |||
10200 | if (lpfc_is_link_up(phba)) | ||
10201 | abtsiocbq->iocb.ulpCommand = CMD_ABORT_XRI_CN; | ||
10202 | else | ||
10203 | abtsiocbq->iocb.ulpCommand = CMD_CLOSE_XRI_CN; | ||
10204 | |||
10205 | /* Setup callback routine and issue the command. */ | ||
10206 | abtsiocbq->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; | ||
10207 | |||
10208 | /* | ||
10209 | * Indicate the IO is being aborted by the driver and set | ||
10210 | * the caller's flag into the aborted IO. | ||
10211 | */ | ||
10212 | iocbq->iocb_flag |= LPFC_DRIVER_ABORTED; | ||
10213 | |||
10214 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
10215 | ring_number = MAX_SLI3_CONFIGURED_RINGS + | ||
10216 | iocbq->fcp_wqidx; | ||
10217 | pring_s4 = &phba->sli.ring[ring_number]; | ||
10218 | /* Note: both hbalock and ring_lock must be set here */ | ||
10219 | spin_lock_irqsave(&pring_s4->ring_lock, iflags); | ||
10220 | ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, | ||
10221 | abtsiocbq, 0); | ||
10222 | spin_unlock_irqrestore(&pring_s4->ring_lock, iflags); | ||
10223 | } else { | ||
10224 | ret_val = __lpfc_sli_issue_iocb(phba, pring->ringno, | ||
10225 | abtsiocbq, 0); | ||
10226 | } | ||
10227 | |||
10228 | |||
10229 | if (ret_val == IOCB_ERROR) | ||
10230 | __lpfc_sli_release_iocbq(phba, abtsiocbq); | ||
10231 | else | ||
10232 | sum++; | ||
10233 | } | ||
10234 | spin_unlock_irq(&phba->hbalock); | ||
10235 | return sum; | ||
10236 | } | ||
10237 | |||
10238 | /** | ||
10121 | * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler | 10239 | * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler |
10122 | * @phba: Pointer to HBA context object. | 10240 | * @phba: Pointer to HBA context object. |
10123 | * @cmdiocbq: Pointer to command iocb. | 10241 | * @cmdiocbq: Pointer to command iocb. |