From 3fe0607a04ed7deea7c048052fd63b8670e7a176 Mon Sep 17 00:00:00 2001 From: "Lu, Han" Date: Wed, 25 Feb 2015 08:26:21 +0800 Subject: [PATCH] ASoC: Intel: remove conflicts when load/unload multiple firmware images Details: 1. Unload all modules on fw_list of dsp when suspend, and reload all modules on fw_list when resume. 2. A DSP expects only one scratch, but hsw_parse_fw_image() allocates scratch blocks for each firmware image it parses. Move the allocate function sst_block_alloc_scratch() out of hsw_parse_fw_image() to make sure a scratch be allocated only after all firmware images be parsed. Signed-off-by: Lu, Han Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-dsp.c | 3 --- sound/soc/intel/sst-haswell-ipc.c | 32 +++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 57039b00efc2..f6e1e6b2b18e 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c @@ -207,9 +207,6 @@ static int hsw_parse_fw_image(struct sst_fw *sst_fw) module = (void *)module + sizeof(*module) + module->mod_size; } - /* allocate scratch mem regions */ - sst_block_alloc_scratch(dsp); - return 0; } diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 8156cc1accb7..6c7052a40e36 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -1870,6 +1870,7 @@ static void sst_hsw_drop_all(struct sst_hsw *hsw) int sst_hsw_dsp_load(struct sst_hsw *hsw) { struct sst_dsp *dsp = hsw->dsp; + struct sst_fw *sst_fw, *t; int ret; dev_dbg(hsw->dev, "loading audio DSP...."); @@ -1886,12 +1887,17 @@ int sst_hsw_dsp_load(struct sst_hsw *hsw) return ret; } - ret = sst_fw_reload(hsw->sst_fw); - if (ret < 0) { - dev_err(hsw->dev, "error: SST FW reload failed\n"); - sst_dsp_dma_put_channel(dsp); - return -ENOMEM; + list_for_each_entry_safe_reverse(sst_fw, t, &dsp->fw_list, list) { + ret = sst_fw_reload(sst_fw); + if (ret < 0) { + dev_err(hsw->dev, "error: SST FW reload failed\n"); + sst_dsp_dma_put_channel(dsp); + return -ENOMEM; + } } + ret = sst_block_alloc_scratch(hsw->dsp); + if (ret < 0) + return -EINVAL; sst_dsp_dma_put_channel(dsp); return 0; @@ -1947,12 +1953,17 @@ int sst_hsw_dsp_runtime_suspend(struct sst_hsw *hsw) int sst_hsw_dsp_runtime_sleep(struct sst_hsw *hsw) { - sst_fw_unload(hsw->sst_fw); - sst_block_free_scratch(hsw->dsp); + struct sst_fw *sst_fw, *t; + struct sst_dsp *dsp = hsw->dsp; + + list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) { + sst_fw_unload(sst_fw); + } + sst_block_free_scratch(dsp); hsw->boot_complete = false; - sst_dsp_sleep(hsw->dsp); + sst_dsp_sleep(dsp); return 0; } @@ -2081,6 +2092,11 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) goto fw_err; } + /* allocate scratch mem regions */ + ret = sst_block_alloc_scratch(hsw->dsp); + if (ret < 0) + goto boot_err; + /* wait for DSP boot completion */ sst_dsp_boot(hsw->dsp); ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete,