Skip to content

Commit 68ded75

Browse files
committed
ASoC: SOF: harden the FW boot sequence
For ACPI platforms, FW booting fails on the first try after unloading and reloasing the SOF module. But trying to reset the DSP and then boot the FW again helps fix the problem. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent 511ef68 commit 68ded75

File tree

1 file changed

+47
-18
lines changed

1 file changed

+47
-18
lines changed

sound/soc/sof/loader.c

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <sound/sof.h>
1515
#include "ops.h"
1616

17+
#define FW_BOOT_RETRIES 5
18+
1719
static int get_ext_windows(struct snd_sof_dev *sdev,
1820
struct sof_ipc_ext_data_hdr *ext_hdr)
1921
{
@@ -507,6 +509,7 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
507509
{
508510
int ret;
509511
int init_core_mask;
512+
int i;
510513

511514
init_waitqueue_head(&sdev->boot_wait);
512515
sdev->boot_complete = false;
@@ -532,25 +535,51 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
532535

533536
dev_dbg(sdev->dev, "booting DSP firmware\n");
534537

535-
/* boot the firmware on the DSP */
536-
ret = snd_sof_dsp_run(sdev);
537-
if (ret < 0) {
538-
dev_err(sdev->dev, "error: failed to reset DSP\n");
539-
return ret;
540-
}
538+
for (i = 0; i < FW_BOOT_RETRIES; i++) {
539+
/* prepare the DSP for FW loading for subsequent tries */
540+
if (i > 0) {
541+
ret = snd_sof_dsp_reset(sdev);
542+
if (ret < 0) {
543+
dev_err(sdev->dev, "error: failed to reset DSP\n");
544+
return ret;
545+
}
546+
}
547+
548+
/* boot the firmware on the DSP */
549+
ret = snd_sof_dsp_run(sdev);
550+
if (ret < 0) {
551+
if (i == FW_BOOT_RETRIES) {
552+
dev_err(sdev->dev, "error: failed to reset DSP\n");
553+
return ret;
554+
}
555+
556+
/* try again */
557+
continue;
558+
}
559+
560+
init_core_mask = ret;
561+
562+
/* now wait for the DSP to boot */
563+
ret = wait_event_timeout(sdev->boot_wait, sdev->boot_complete,
564+
msecs_to_jiffies(sdev->boot_timeout));
565+
if (ret == 0) {
566+
if (i == FW_BOOT_RETRIES) {
567+
dev_err(sdev->dev,
568+
"error: firmware boot failure after %d iterations\n",
569+
i);
570+
snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS |
571+
SOF_DBG_MBOX |
572+
SOF_DBG_TEXT |
573+
SOF_DBG_PCI);
574+
575+
/* FW_READY msg ignored from now on */
576+
sdev->boot_complete = true;
577+
return -EIO;
578+
}
579+
}
541580

542-
init_core_mask = ret;
543-
544-
/* now wait for the DSP to boot */
545-
ret = wait_event_timeout(sdev->boot_wait, sdev->boot_complete,
546-
msecs_to_jiffies(sdev->boot_timeout));
547-
if (ret == 0) {
548-
dev_err(sdev->dev, "error: firmware boot failure\n");
549-
snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX |
550-
SOF_DBG_TEXT | SOF_DBG_PCI);
551-
/* after this point FW_READY msg should be ignored */
552-
sdev->boot_complete = true;
553-
return -EIO;
581+
/* FW boot successful */
582+
break;
554583
}
555584

556585
dev_info(sdev->dev, "firmware boot complete\n");

0 commit comments

Comments
 (0)