]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
scsi: qla2xxx: Chip reset uses wrong lock during IO flush.
authorQuinn Tran <quinn.tran@cavium.com>
Thu, 28 Dec 2017 20:33:13 +0000 (12:33 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 4 Jan 2018 04:41:05 +0000 (23:41 -0500)
As part of chip reset, all commands from all QPairs are
flushed. This patch fixes code to use Q Pair lock for flush
instead of using old hardware_lock.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_os.c

index 029b95b2bd8ad056d071127ce1ca4a0350ecdc2a..2e4bfb7aabf74cd100b10c9867e1bf805370c2ec 100644 (file)
@@ -1704,93 +1704,103 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
        return QLA_SUCCESS;
 }
 
-void
-qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
+static void
+__qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
 {
-       int que, cnt, status;
+       int cnt, status;
        unsigned long flags;
        srb_t *sp;
+       scsi_qla_host_t *vha = qp->vha;
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req;
        struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
        struct qla_tgt_cmd *cmd;
        uint8_t trace = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
-       for (que = 0; que < ha->max_req_queues; que++) {
-               req = ha->req_q_map[que];
-               if (!req)
-                       continue;
-               if (!req->outstanding_cmds)
-                       continue;
-               for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
-                       sp = req->outstanding_cmds[cnt];
-                       if (sp) {
-                               req->outstanding_cmds[cnt] = NULL;
-                               if (sp->cmd_type == TYPE_SRB) {
-                                       if (sp->type == SRB_NVME_CMD ||
-                                           sp->type == SRB_NVME_LS) {
-                                               sp_get(sp);
-                                               spin_unlock_irqrestore(
-                                                   &ha->hardware_lock, flags);
-                                               qla_nvme_abort(ha, sp);
-                                               spin_lock_irqsave(
-                                                   &ha->hardware_lock, flags);
-                                       } else if (GET_CMD_SP(sp) &&
-                                           !ha->flags.eeh_busy &&
-                                           (!test_bit(ABORT_ISP_ACTIVE,
-                                               &vha->dpc_flags)) &&
-                                           (sp->type == SRB_SCSI_CMD)) {
-                                               /*
-                                                * Don't abort commands in
-                                                * adapter during EEH
-                                                * recovery as it's not
-                                                * accessible/responding.
-                                                *
-                                                * Get a reference to the sp
-                                                * and drop the lock. The
-                                                * reference ensures this
-                                                * sp->done() call and not the
-                                                * call in qla2xxx_eh_abort()
-                                                * ends the SCSI command (with
-                                                * result 'res').
-                                                */
-                                               sp_get(sp);
-                                               spin_unlock_irqrestore(
-                                                   &ha->hardware_lock, flags);
-                                               status = qla2xxx_eh_abort(
-                                                   GET_CMD_SP(sp));
-                                               spin_lock_irqsave(
-                                                   &ha->hardware_lock, flags);
-                                               /*
-                                                * Get rid of extra reference
-                                                * if immediate exit from
-                                                * ql2xxx_eh_abort
-                                                */
-                                               if (status == FAILED &&
-                                                   (qla2x00_isp_reg_stat(ha)))
-                                                       atomic_dec(
-                                                           &sp->ref_count);
-                                       }
-                                       sp->done(sp, res);
-                               } else {
-                                       if (!vha->hw->tgt.tgt_ops || !tgt ||
-                                           qla_ini_mode_enabled(vha)) {
-                                               if (!trace)
-                                                       ql_dbg(ql_dbg_tgt_mgt,
-                                                           vha, 0xf003,
-                                                           "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
-                                                           vha->dpc_flags);
-                                               continue;
-                                       }
-                                       cmd = (struct qla_tgt_cmd *)sp;
-                                       qlt_abort_cmd_on_host_reset(cmd->vha,
-                                           cmd);
+       spin_lock_irqsave(qp->qp_lock_ptr, flags);
+       req = qp->req;
+       for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
+               sp = req->outstanding_cmds[cnt];
+               if (sp) {
+                       req->outstanding_cmds[cnt] = NULL;
+                       if (sp->cmd_type == TYPE_SRB) {
+                               if (sp->type == SRB_NVME_CMD ||
+                                   sp->type == SRB_NVME_LS) {
+                                       sp_get(sp);
+                                       spin_unlock_irqrestore(qp->qp_lock_ptr,
+                                           flags);
+                                       qla_nvme_abort(ha, sp);
+                                       spin_lock_irqsave(qp->qp_lock_ptr,
+                                           flags);
+                               } else if (GET_CMD_SP(sp) &&
+                                   !ha->flags.eeh_busy &&
+                                   (!test_bit(ABORT_ISP_ACTIVE,
+                                       &vha->dpc_flags)) &&
+                                   (sp->type == SRB_SCSI_CMD)) {
+                                       /*
+                                        * Don't abort commands in
+                                        * adapter during EEH
+                                        * recovery as it's not
+                                        * accessible/responding.
+                                        *
+                                        * Get a reference to the sp
+                                        * and drop the lock. The
+                                        * reference ensures this
+                                        * sp->done() call and not the
+                                        * call in qla2xxx_eh_abort()
+                                        * ends the SCSI command (with
+                                        * result 'res').
+                                        */
+                                       sp_get(sp);
+                                       spin_unlock_irqrestore(qp->qp_lock_ptr,
+                                           flags);
+                                       status = qla2xxx_eh_abort(
+                                           GET_CMD_SP(sp));
+                                       spin_lock_irqsave(qp->qp_lock_ptr,
+                                           flags);
+                                       /*
+                                        * Get rid of extra reference
+                                        * if immediate exit from
+                                        * ql2xxx_eh_abort
+                                        */
+                                       if (status == FAILED &&
+                                           (qla2x00_isp_reg_stat(ha)))
+                                               atomic_dec(
+                                                   &sp->ref_count);
+                               }
+                               sp->done(sp, res);
+                       } else {
+                               if (!vha->hw->tgt.tgt_ops || !tgt ||
+                                   qla_ini_mode_enabled(vha)) {
+                                       if (!trace)
+                                               ql_dbg(ql_dbg_tgt_mgt,
+                                                   vha, 0xf003,
+                                                   "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
+                                                   vha->dpc_flags);
+                                       continue;
                                }
+                               cmd = (struct qla_tgt_cmd *)sp;
+                               qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
                        }
                }
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
+}
+
+void
+qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
+{
+       int que;
+       struct qla_hw_data *ha = vha->hw;
+
+       __qla2x00_abort_all_cmds(ha->base_qpair, res);
+
+       for (que = 0; que < ha->max_qpairs; que++) {
+               if (!ha->queue_pair_map[que])
+                       continue;
+
+               __qla2x00_abort_all_cmds(ha->queue_pair_map[que], res);
+       }
 }
 
 static int