scsi: qla2xxx: Adjust IOCB resource on qpair create
authorQuinn Tran <qutran@marvell.com>
Fri, 14 Jul 2023 07:00:56 +0000 (12:30 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sun, 23 Jul 2023 20:27:47 +0000 (16:27 -0400)
During NVMe queue creation, a new qpair is created. FW resource limit needs
to be re-adjusted to take into account the new qpair. Otherwise, NVMe
command can not go through.  This issue was discovered while
testing/forcing FW execution to fail at load time.

Add call to readjust IOCB and exchange limit.

In addition, get FW state command and require FW to be running. Otherwise,
error is generated.

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/20230714070104.40052-3-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nvme.c

index ba7831f24734f176de8d6575d5d42aa5d9f0478d..33fba9d6296933608dee464601c6360fa619469c 100644 (file)
@@ -143,6 +143,7 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess);
 void qla_edif_clear_appdata(struct scsi_qla_host *vha,
                            struct fc_port *fcport);
 const char *sc_to_str(uint16_t cmd);
+void qla_adjust_iocb_limit(scsi_qla_host_t *vha);
 
 /*
  * Global Data in qla_os.c source file.
index 5c2a646265e4c466ed7158b1623d93534f1705e9..eb25fc2451d3cad6b40e8eb4cb07502c2084d4b8 100644 (file)
@@ -4153,41 +4153,55 @@ out:
        return ha->flags.lr_detected;
 }
 
-void qla_init_iocb_limit(scsi_qla_host_t *vha)
+static void __qla_adjust_iocb_limit(struct qla_qpair *qpair)
 {
-       u16 i, num_qps;
-       u32 limit;
-       struct qla_hw_data *ha = vha->hw;
+       u8 num_qps;
+       u16 limit;
+       struct qla_hw_data *ha = qpair->vha->hw;
 
        num_qps = ha->num_qpairs + 1;
        limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100;
 
-       ha->base_qpair->fwres.iocbs_total = ha->orig_fw_iocb_count;
-       ha->base_qpair->fwres.iocbs_limit = limit;
-       ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps;
-       ha->base_qpair->fwres.iocbs_used = 0;
+       qpair->fwres.iocbs_total = ha->orig_fw_iocb_count;
+       qpair->fwres.iocbs_limit = limit;
+       qpair->fwres.iocbs_qp_limit = limit / num_qps;
+
+       qpair->fwres.exch_total = ha->orig_fw_xcb_count;
+       qpair->fwres.exch_limit = (ha->orig_fw_xcb_count *
+                                  QLA_IOCB_PCT_LIMIT) / 100;
+}
+
+void qla_init_iocb_limit(scsi_qla_host_t *vha)
+{
+       u8 i;
+       struct qla_hw_data *ha = vha->hw;
 
-       ha->base_qpair->fwres.exch_total = ha->orig_fw_xcb_count;
-       ha->base_qpair->fwres.exch_limit = (ha->orig_fw_xcb_count *
-                                           QLA_IOCB_PCT_LIMIT) / 100;
+        __qla_adjust_iocb_limit(ha->base_qpair);
+       ha->base_qpair->fwres.iocbs_used = 0;
        ha->base_qpair->fwres.exch_used  = 0;
 
        for (i = 0; i < ha->max_qpairs; i++) {
                if (ha->queue_pair_map[i])  {
-                       ha->queue_pair_map[i]->fwres.iocbs_total =
-                               ha->orig_fw_iocb_count;
-                       ha->queue_pair_map[i]->fwres.iocbs_limit = limit;
-                       ha->queue_pair_map[i]->fwres.iocbs_qp_limit =
-                               limit / num_qps;
+                       __qla_adjust_iocb_limit(ha->queue_pair_map[i]);
                        ha->queue_pair_map[i]->fwres.iocbs_used = 0;
-                       ha->queue_pair_map[i]->fwres.exch_total = ha->orig_fw_xcb_count;
-                       ha->queue_pair_map[i]->fwres.exch_limit =
-                               (ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100;
                        ha->queue_pair_map[i]->fwres.exch_used = 0;
                }
        }
 }
 
+void qla_adjust_iocb_limit(scsi_qla_host_t *vha)
+{
+       u8 i;
+       struct qla_hw_data *ha = vha->hw;
+
+       __qla_adjust_iocb_limit(ha->base_qpair);
+
+       for (i = 0; i < ha->max_qpairs; i++) {
+               if (ha->queue_pair_map[i])
+                       __qla_adjust_iocb_limit(ha->queue_pair_map[i]);
+       }
+}
+
 /**
  * qla2x00_setup_chip() - Load and start RISC firmware.
  * @vha: HA context
index 254fd4c64262890b177dab830c08f1e474e227ea..b05f930378756e4f650612cbf7f858ea8ea870cd 100644 (file)
@@ -2213,6 +2213,9 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054,
            "Entered %s.\n", __func__);
 
+       if (!ha->flags.fw_started)
+               return QLA_FUNCTION_FAILED;
+
        mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
        mcp->out_mb = MBX_0;
        if (IS_FWI2_CAPABLE(vha->hw))
index 86e85f2f4782f6c1f52febe57645e448c7e111b6..6769c40287b9a8785a60bcd568d4da9873f354d1 100644 (file)
@@ -132,6 +132,7 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport,
                               "Failed to allocate qpair\n");
                        return -EINVAL;
                }
+               qla_adjust_iocb_limit(vha);
        }
        *handle = qpair;