The SOF_FW_CRASHED state is meant to indicate the unfortunate case when the
firmware has crashed after a successful boot.
IPC tx timeout is not treated as indication of a firmware crash as it tends
to happen regularly while the firmware is operational.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Paul Olaru <paul.olaru@oss.nxp.com>
Link: https://lore.kernel.org/r/20211223113628.18582-8-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
 
        {SOF_FW_BOOT_FAILED, "SOF_FW_BOOT_FAILED"},
        {SOF_FW_BOOT_READY_FAILED, "SOF_FW_BOOT_READY_FAILED"},
        {SOF_FW_BOOT_COMPLETE, "SOF_FW_BOOT_COMPLETE"},
+       {SOF_FW_CRASHED, "SOF_FW_CRASHED"},
 };
 
 static void snd_sof_dbg_print_fw_state(struct snd_sof_dev *sdev)
 
        struct snd_sof_ipc_msg *msg;
        int ret;
 
-       if (ipc->disable_ipc_tx)
+       if (ipc->disable_ipc_tx || sdev->fw_state == SOF_FW_CRASHED)
                return -ENODEV;
 
        /*
 
 
                snd_sof_dsp_dbg_dump(sdev, "DSP panic!",
                                     SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
+               if (non_recoverable)
+                       sof_set_fw_state(sdev, SOF_FW_CRASHED);
                snd_sof_trace_notify_for_error(sdev);
        }
 }
 
        /* will suspend to S3 by default */
        sdev->system_suspend_target = SOF_SUSPEND_S3;
 
+       /*
+        * if the firmware is crashed then we try to aim for S3 to reboot the
+        * firmware
+        */
+       if (sdev->fw_state == SOF_FW_CRASHED)
+               return 0;
+
        if (!desc->use_acpi_target_states)
                return 0;
 
 
        SOF_FW_BOOT_FAILED,
        SOF_FW_BOOT_READY_FAILED, /* firmware booted but fw_ready op failed */
        SOF_FW_BOOT_COMPLETE,
+       SOF_FW_CRASHED,
 };
 
 /*