aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2014-04-04 13:52:31 -0400
committerChristoph Hellwig <hch@lst.de>2014-06-02 12:29:01 -0400
commit98912dda4d287a7bc6f0b7a91cceb0fedd1492f6 (patch)
treee07fe118abc3c93d608bb5ae183f6cac483d20a3 /drivers/scsi/lpfc
parentf38fa0bb7c4a54dc7eff622adc6fa7cf763d834d (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.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c25
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c118
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 *,
311int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd); 311int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd);
312int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, 312int 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);
314int
315lpfc_sli_abort_taskmgmt(struct lpfc_vport *, struct lpfc_sli_ring *,
316 uint16_t, uint64_t, lpfc_ctx_cmd);
314 317
315void lpfc_mbox_timeout(unsigned long); 318void lpfc_mbox_timeout(unsigned long);
316void lpfc_mbox_timeout_handler(struct lpfc_hba *); 319void 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 **/
10142int
10143lpfc_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.