return pqi_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID);
 }
 
+#define PQI_DRIVER_SCRATCH_PQI_MODE                    0x1
+#define PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED         0x2
+
 static inline enum pqi_ctrl_mode pqi_get_ctrl_mode(struct pqi_ctrl_info *ctrl_info)
 {
-       return sis_read_driver_scratch(ctrl_info);
+       return sis_read_driver_scratch(ctrl_info) & PQI_DRIVER_SCRATCH_PQI_MODE ? PQI_MODE : SIS_MODE;
 }
 
 static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info *ctrl_info,
        enum pqi_ctrl_mode mode)
 {
-       sis_write_driver_scratch(ctrl_info, mode);
+       u32 driver_scratch;
+
+       driver_scratch = sis_read_driver_scratch(ctrl_info);
+
+       if (mode == PQI_MODE)
+               driver_scratch |= PQI_DRIVER_SCRATCH_PQI_MODE;
+       else
+               driver_scratch &= ~PQI_DRIVER_SCRATCH_PQI_MODE;
+
+       sis_write_driver_scratch(ctrl_info, driver_scratch);
+}
+
+static inline bool pqi_is_fw_triage_supported(struct pqi_ctrl_info *ctrl_info)
+{
+       return (sis_read_driver_scratch(ctrl_info) & PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED) != 0;
+}
+
+static inline void pqi_save_fw_triage_setting(struct pqi_ctrl_info *ctrl_info, bool is_supported)
+{
+       u32 driver_scratch;
+
+       driver_scratch = sis_read_driver_scratch(ctrl_info);
+
+       if (is_supported)
+               driver_scratch |= PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED;
+       else
+               driver_scratch &= ~PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED;
+
+       sis_write_driver_scratch(ctrl_info, driver_scratch);
 }
 
 static inline void pqi_ctrl_block_scan(struct pqi_ctrl_info *ctrl_info)
                ctrl_info->unique_wwid_in_report_phys_lun_supported =
                        firmware_feature->enabled;
                break;
+               pqi_save_fw_triage_setting(ctrl_info, firmware_feature->enabled);
        }
 
        pqi_firmware_feature_status(ctrl_info, firmware_feature);
        u32 product_id;
 
        if (reset_devices) {
+               if (pqi_is_fw_triage_supported(ctrl_info)) {
+                       rc = sis_wait_for_fw_triage_completion(ctrl_info);
+                       if (rc)
+                               return rc;
+               }
                sis_soft_reset(ctrl_info);
                msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ);
        } else {
 
 #define SIS_BASE_STRUCT_REVISION               9
 #define SIS_BASE_STRUCT_ALIGNMENT              16
 
+#define SIS_CTRL_KERNEL_FW_TRIAGE              0x3
 #define SIS_CTRL_KERNEL_UP                     0x80
 #define SIS_CTRL_KERNEL_PANIC                  0x100
 #define SIS_CTRL_READY_TIMEOUT_SECS            180
 #define SIS_CTRL_READY_RESUME_TIMEOUT_SECS     90
 #define SIS_CTRL_READY_POLL_INTERVAL_MSECS     10
 
+enum sis_fw_triage_status {
+       FW_TRIAGE_NOT_STARTED = 0,
+       FW_TRIAGE_STARTED,
+       FW_TRIAGE_COND_INVALID,
+       FW_TRIAGE_COMPLETED
+};
+
 #pragma pack(1)
 
 /* for use with SIS_CMD_INIT_BASE_STRUCT_ADDRESS command */
        return readl(&ctrl_info->registers->sis_driver_scratch);
 }
 
+static inline enum sis_fw_triage_status
+       sis_read_firmware_triage_status(struct pqi_ctrl_info *ctrl_info)
+{
+       return ((enum sis_fw_triage_status)(readl(&ctrl_info->registers->sis_firmware_status) &
+               SIS_CTRL_KERNEL_FW_TRIAGE));
+}
+
 void sis_soft_reset(struct pqi_ctrl_info *ctrl_info)
 {
        writel(SIS_SOFT_RESET,
                &ctrl_info->registers->sis_host_to_ctrl_doorbell);
 }
 
+#define SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS              300
+#define SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS                1
+
+int sis_wait_for_fw_triage_completion(struct pqi_ctrl_info *ctrl_info)
+{
+       int rc;
+       enum sis_fw_triage_status status;
+       unsigned long timeout;
+
+       timeout = (SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS * PQI_HZ) + jiffies;
+       while (1) {
+               status = sis_read_firmware_triage_status(ctrl_info);
+               if (status == FW_TRIAGE_COND_INVALID) {
+                       dev_err(&ctrl_info->pci_dev->dev,
+                               "firmware triage condition invalid\n");
+                       rc = -EINVAL;
+                       break;
+               } else if (status == FW_TRIAGE_NOT_STARTED ||
+                       status == FW_TRIAGE_COMPLETED) {
+                       rc = 0;
+                       break;
+               }
+
+               if (time_after(jiffies, timeout)) {
+                       dev_err(&ctrl_info->pci_dev->dev,
+                               "timed out waiting for firmware triage status\n");
+                       rc = -ETIMEDOUT;
+                       break;
+               }
+
+               ssleep(SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS);
+       }
+
+       return rc;
+}
+
 static void __attribute__((unused)) verify_structures(void)
 {
        BUILD_BUG_ON(offsetof(struct sis_base_struct,