]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: qla2xxx: Add support to report MPI FW state
authorNilesh Javali <njavali@marvell.com>
Thu, 5 Mar 2026 09:33:37 +0000 (15:03 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 7 Mar 2026 16:23:28 +0000 (11:23 -0500)
MPI firmware state was returned as 0.  Get MPI FW state to proceed with
flash image validation.

A new sysfs node 'mpi_fw_state' is added to report MPI firmware state:

    /sys/class/scsi_host/hostXX/mpi_fw_state

Fixes: d74181ca110e ("scsi: qla2xxx: Add bsg interface to support firmware img validation")
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260305093337.2007205-1-njavali@marvell.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c

index 2e584a8bf66b252ac6bd056a776de22127d1c2a8..6a05ce195aa05bf3c488b492aefefede236cd2ab 100644 (file)
@@ -1638,7 +1638,7 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
 {
        scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
        int rval = QLA_FUNCTION_FAILED;
-       uint16_t state[6];
+       uint16_t state[16];
        uint32_t pstate;
 
        if (IS_QLAFX00(vha->hw)) {
@@ -2402,6 +2402,63 @@ qla2x00_dport_diagnostics_show(struct device *dev,
            vha->dport_data[0], vha->dport_data[1],
            vha->dport_data[2], vha->dport_data[3]);
 }
+
+static ssize_t
+qla2x00_mpi_fw_state_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+       int rval = QLA_FUNCTION_FAILED;
+       u16 state[16];
+       u16 mpi_state;
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!(IS_QLA27XX(ha) || IS_QLA28XX(ha)))
+               return scnprintf(buf, PAGE_SIZE,
+                               "MPI state reporting is not supported for this HBA.\n");
+
+       memset(state, 0, sizeof(state));
+
+       mutex_lock(&vha->hw->optrom_mutex);
+       if (qla2x00_chip_is_down(vha)) {
+               mutex_unlock(&vha->hw->optrom_mutex);
+               ql_dbg(ql_dbg_user, vha, 0x70df,
+                      "ISP reset is in progress, failing mpi_fw_state.\n");
+               return -EBUSY;
+       } else if (vha->hw->flags.eeh_busy) {
+               mutex_unlock(&vha->hw->optrom_mutex);
+               ql_dbg(ql_dbg_user, vha, 0x70ea,
+                      "HBA in PCI error state, failing mpi_fw_state.\n");
+               return -EBUSY;
+       }
+
+       rval = qla2x00_get_firmware_state(vha, state);
+       mutex_unlock(&vha->hw->optrom_mutex);
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_user, vha, 0x70eb,
+                      "MB Command to retrieve MPI state failed (%d), failing mpi_fw_state.\n",
+                               rval);
+               return -EIO;
+       }
+
+       mpi_state = state[11];
+
+       if (!(mpi_state & BIT_15))
+               return scnprintf(buf, PAGE_SIZE,
+                                "MPI firmware state reporting is not supported by this firmware. (0x%02x)\n",
+                               mpi_state);
+
+       if (!(mpi_state & BIT_8))
+               return scnprintf(buf, PAGE_SIZE,
+                                "MPI firmware is disabled. (0x%02x)\n",
+                               mpi_state);
+
+       return scnprintf(buf, PAGE_SIZE,
+                        "MPI firmware is enabled, state is %s. (0x%02x)\n",
+                        mpi_state & BIT_9 ? "active" : "inactive",
+                        mpi_state);
+}
+
 static DEVICE_ATTR(dport_diagnostics, 0444,
           qla2x00_dport_diagnostics_show, NULL);
 
@@ -2469,6 +2526,8 @@ static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show,
     qla2x00_port_speed_store);
 static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL);
 static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL);
+static DEVICE_ATTR(mpi_fw_state, 0444, qla2x00_mpi_fw_state_show, NULL);
+
 
 static struct attribute *qla2x00_host_attrs[] = {
        &dev_attr_driver_version.attr.attr,
@@ -2517,6 +2576,7 @@ static struct attribute *qla2x00_host_attrs[] = {
        &dev_attr_qlini_mode.attr,
        &dev_attr_ql2xiniexchg.attr,
        &dev_attr_ql2xexchoffld.attr,
+       &dev_attr_mpi_fw_state.attr,
        NULL,
 };
 
index 730c42b1a7b9d7179b7c60d5c658962488f09759..e746c9274cdeda15b83fcf6fb3d93c2e96e0cdd2 100644 (file)
@@ -4914,7 +4914,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
        unsigned long   wtime, mtime, cs84xx_time;
        uint16_t        min_wait;       /* Minimum wait time if loop is down */
        uint16_t        wait_time;      /* Wait time if loop is coming ready */
-       uint16_t        state[6];
+       uint16_t        state[16];
        struct qla_hw_data *ha = vha->hw;
 
        if (IS_QLAFX00(vha->hw))
index 0d598be6f3eabc5ddf580c40bc5cd37fbdb169d0..44e310f1a3708fadd16c6c330c816ab3705a6dd6 100644 (file)
@@ -2268,6 +2268,13 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
                mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
        else
                mcp->in_mb = MBX_1|MBX_0;
+
+       if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+               mcp->mb[12] = 0;
+               mcp->out_mb |= MBX_12;
+               mcp->in_mb |= MBX_12;
+       }
+
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(vha, mcp);
@@ -2280,6 +2287,8 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
                states[3] = mcp->mb[4];
                states[4] = mcp->mb[5];
                states[5] = mcp->mb[6];  /* DPORT status */
+               if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+                       states[11] = mcp->mb[12]; /* MPI state. */
        }
 
        if (rval != QLA_SUCCESS) {