]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: qla2xxx: Fix task management cmd failure
authorQuinn Tran <qutran@marvell.com>
Fri, 28 Apr 2023 07:53:34 +0000 (00:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2023 08:22:31 +0000 (10:22 +0200)
[ Upstream commit 9803fb5d27597ea98f2e05b0b6cfc48ae808458e ]

Task management cmd failed with status 30h which means
FW is not able to finish processing one task management
before another task management for the same lun.
Hence add wait for completion of marker to space it out.

Reported-by: kernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202304271802.uCZfwQC1-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-3-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com <mailto:himanshu.madhani@oracle.com>>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c

index d4b8d9dd8106ddcf8bdf591e4926f0555614fd6c..ca63aa8f33b5d48de7e8ea75343eaae3ac57083e 100644 (file)
@@ -458,6 +458,7 @@ struct tmf_arg {
        struct scsi_qla_host *vha;
        u64 lun;
        u32 flags;
+       uint8_t modifier;
 };
 
 struct els_logo_payload {
@@ -539,6 +540,10 @@ struct srb_iocb {
                        uint32_t data;
                        struct completion comp;
                        __le16 comp_status;
+
+                       uint8_t modifier;
+                       uint8_t vp_index;
+                       uint16_t loop_id;
                } tmf;
                struct {
 #define SRB_FXDISC_REQ_DMA_VALID       BIT_0
@@ -642,6 +647,7 @@ struct srb_iocb {
 #define SRB_SA_UPDATE  25
 #define SRB_ELS_CMD_HST_NOLOGIN 26
 #define SRB_SA_REPLACE 27
+#define SRB_MARKER     28
 
 struct qla_els_pt_arg {
        u8 els_opcode;
index f64c238e3a45bd92fd43af62b9a0e1761a315fa5..9d9b16f7f34a664ab7230665fab8ea2879072a60 100644 (file)
@@ -2015,6 +2015,80 @@ qla2x00_tmf_iocb_timeout(void *data)
        }
 }
 
+static void qla_marker_sp_done(srb_t *sp, int res)
+{
+       struct srb_iocb *tmf = &sp->u.iocb_cmd;
+
+       if (res != QLA_SUCCESS)
+               ql_dbg(ql_dbg_taskm, sp->vha, 0x8004,
+                   "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n",
+                   sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags,
+                   sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id);
+
+       complete(&tmf->u.tmf.comp);
+}
+
+#define  START_SP_W_RETRIES(_sp, _rval) \
+{\
+       int cnt = 5; \
+       do { \
+               _rval = qla2x00_start_sp(_sp); \
+               if (_rval == EAGAIN) \
+                       msleep(1); \
+               else \
+                       break; \
+               cnt--; \
+       } while (cnt); \
+}
+
+static int
+qla26xx_marker(struct tmf_arg *arg)
+{
+       struct scsi_qla_host *vha = arg->vha;
+       struct srb_iocb *tm_iocb;
+       srb_t *sp;
+       int rval = QLA_FUNCTION_FAILED;
+       fc_port_t *fcport = arg->fcport;
+
+       /* ref: INIT */
+       sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
+       if (!sp)
+               goto done;
+
+       sp->type = SRB_MARKER;
+       sp->name = "marker";
+       qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done);
+       sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;
+
+       tm_iocb = &sp->u.iocb_cmd;
+       init_completion(&tm_iocb->u.tmf.comp);
+       tm_iocb->u.tmf.modifier = arg->modifier;
+       tm_iocb->u.tmf.lun = arg->lun;
+       tm_iocb->u.tmf.loop_id = fcport->loop_id;
+       tm_iocb->u.tmf.vp_index = vha->vp_idx;
+
+       START_SP_W_RETRIES(sp, rval);
+
+       ql_dbg(ql_dbg_taskm, vha, 0x8006,
+           "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
+           sp->handle, fcport->loop_id, fcport->d_id.b24,
+           arg->modifier, arg->lun, sp->qpair->id, rval);
+
+       if (rval != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x8031,
+                   "Marker IOCB failed (%x).\n", rval);
+               goto done_free_sp;
+       }
+
+       wait_for_completion(&tm_iocb->u.tmf.comp);
+
+done_free_sp:
+       /* ref: INIT */
+       kref_put(&sp->cmd_kref, qla2x00_sp_release);
+done:
+       return rval;
+}
+
 static void qla2x00_tmf_sp_done(srb_t *sp, int res)
 {
        struct srb_iocb *tmf = &sp->u.iocb_cmd;
@@ -2028,7 +2102,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
        struct scsi_qla_host *vha = arg->vha;
        struct srb_iocb *tm_iocb;
        srb_t *sp;
-       unsigned long flags;
        int rval = QLA_FUNCTION_FAILED;
 
        fc_port_t *fcport = arg->fcport;
@@ -2050,11 +2123,12 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
        tm_iocb->u.tmf.flags = arg->flags;
        tm_iocb->u.tmf.lun = arg->lun;
 
-       rval = qla2x00_start_sp(sp);
+       START_SP_W_RETRIES(sp, rval);
+
        ql_dbg(ql_dbg_taskm, vha, 0x802f,
-           "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n",
-           sp->handle, fcport->loop_id, fcport->d_id.b.domain,
-           fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags);
+           "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n",
+           sp->handle, fcport->loop_id, fcport->d_id.b24,
+           arg->flags, arg->lun, sp->qpair->id, rval);
 
        if (rval != QLA_SUCCESS)
                goto done_free_sp;
@@ -2067,17 +2141,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
                    "TM IOCB failed (%x).\n", rval);
        }
 
-       if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) {
-               flags = tm_iocb->u.tmf.flags;
-               if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|
-                       TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA))
-                       flags = MK_SYNC_ID_LUN;
-               else
-                       flags = MK_SYNC_ID;
-
-               qla2x00_marker(vha, sp->qpair,
-                   sp->fcport->loop_id, arg->lun, flags);
-       }
+       if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
+               rval = qla26xx_marker(arg);
 
 done_free_sp:
        /* ref: INIT */
@@ -2101,6 +2166,11 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
        a.fcport = fcport;
        a.lun = lun;
 
+       if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA))
+               a.modifier = MK_SYNC_ID_LUN;
+       else
+               a.modifier = MK_SYNC_ID;
+
        if (vha->hw->mqenable) {
                for (i = 0; i < vha->hw->num_qpairs; i++) {
                        qpair = vha->hw->queue_pair_map[i];
index ac82392c22eed42f5f8fc5f8e8b99ecfb0da846f..c9a686f06d29d7d6061c6031db4333eaa6c094a6 100644 (file)
@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
                return (QLA_FUNCTION_FAILED);
        }
 
+       mrk24 = (struct mrk_entry_24xx *)mrk;
+
        mrk->entry_type = MARKER_TYPE;
        mrk->modifier = type;
        if (type != MK_SYNC_ALL) {
                if (IS_FWI2_CAPABLE(ha)) {
-                       mrk24 = (struct mrk_entry_24xx *) mrk;
                        mrk24->nport_handle = cpu_to_le16(loop_id);
                        int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
                        host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
                        mrk24->vp_index = vha->vp_idx;
-                       mrk24->handle = make_handle(req->id, mrk24->handle);
                } else {
                        SET_TARGET_ID(ha, mrk->target, loop_id);
                        mrk->lun = cpu_to_le16((uint16_t)lun);
                }
        }
+
+       if (IS_FWI2_CAPABLE(ha))
+               mrk24->handle = QLA_SKIP_HANDLE;
+
        wmb();
 
        qla2x00_start_iocbs(vha, req);
@@ -3860,9 +3864,9 @@ int qla_get_iocbs_resource(struct srb *sp)
        case SRB_NACK_LOGO:
        case SRB_LOGOUT_CMD:
        case SRB_CTRL_VP:
-               push_it_through = true;
-               fallthrough;
+       case SRB_MARKER:
        default:
+               push_it_through = true;
                get_exch = false;
        }
 
@@ -3878,6 +3882,19 @@ int qla_get_iocbs_resource(struct srb *sp)
        return qla_get_fw_resources(sp->qpair, &sp->iores);
 }
 
+static void
+qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
+{
+       mrk->entry_type = MARKER_TYPE;
+       mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier;
+       if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) {
+               mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id);
+               int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun);
+               host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
+               mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index;
+       }
+}
+
 int
 qla2x00_start_sp(srb_t *sp)
 {
@@ -3981,6 +3998,9 @@ qla2x00_start_sp(srb_t *sp)
        case SRB_SA_REPLACE:
                qla24xx_sa_replace_iocb(sp, pkt);
                break;
+       case SRB_MARKER:
+               qla_marker_iocb(sp, pkt);
+               break;
        default:
                break;
        }
index 665959938e5e3b82b828ed94b4e27a40604ef83a..08d43f43995ef927d64eb7e934b84f32369ae5dc 100644 (file)
@@ -3737,6 +3737,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
        return rc;
 }
 
+static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+       struct mrk_entry_24xx *pkt)
+{
+       const char func[] = "MRK-IOCB";
+       srb_t *sp;
+       int res = QLA_SUCCESS;
+
+       if (!IS_FWI2_CAPABLE(vha->hw))
+               return;
+
+       sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+       if (!sp)
+               return;
+
+       if (pkt->entry_status) {
+               ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n");
+               res = QLA_COMMAND_ERROR;
+       }
+       sp->u.iocb_cmd.u.tmf.data = res;
+       sp->done(sp, res);
+}
+
 /**
  * qla24xx_process_response_queue() - Process response queue entries.
  * @vha: SCSI driver HA context
@@ -3858,9 +3880,7 @@ process_err:
                                        (struct nack_to_isp *)pkt);
                        break;
                case MARKER_TYPE:
-                       /* Do nothing in this case, this check is to prevent it
-                        * from falling into default case
-                        */
+                       qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt);
                        break;
                case ABORT_IOCB_TYPE:
                        qla24xx_abort_iocb_entry(vha, rsp->req,