420 lines
14 KiB
Diff
420 lines
14 KiB
Diff
From 44634a3f2a443f2a5744ddad042479481ebd7002 Mon Sep 17 00:00:00 2001
|
|
From: Pardha Saradhi K <pardha.saradhi.kesapragada@intel.com>
|
|
Date: Thu, 4 Jan 2018 19:40:48 +0530
|
|
Subject: [PATCH 332/550] ASoC: Intel: Skylake: validate the downloaded
|
|
firmware
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Print the firmware version downloaded and verify if it is
|
|
equal or greater than the minimum supported version for
|
|
the existing driver. Report error and exit driver
|
|
initialization if downloaded firmware is not compatible
|
|
with current driver.
|
|
|
|
Change-Id: I6e0f046d88123c9c216ac9a1c9054f37661e1bfe
|
|
Signed-off-by: Prakash, Divya1 <divya1.prakash@intel.com>
|
|
Signed-off-by: Mohit Sinha <mohit.sinha@intel.com>
|
|
Signed-off-by: Pardha Saradhi K <pardha.saradhi.kesapragada@intel.com>
|
|
Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@intel.com>
|
|
Reviewed-on:
|
|
Reviewed-by: Rojewski, Cezary <cezary.rojewski@intel.com>
|
|
Tested-by: Rojewski, Cezary <cezary.rojewski@intel.com>
|
|
---
|
|
sound/soc/intel/skylake/bxt-sst.c | 17 ++++++++++++++--
|
|
sound/soc/intel/skylake/cnl-sst-dsp.h | 2 +-
|
|
sound/soc/intel/skylake/cnl-sst.c | 11 ++++++++--
|
|
sound/soc/intel/skylake/skl-messages.c | 22 +++++++++++---------
|
|
sound/soc/intel/skylake/skl-sst-dsp.h | 27 +++++++++++++++++++++++--
|
|
sound/soc/intel/skylake/skl-sst-ipc.h | 7 -------
|
|
sound/soc/intel/skylake/skl-sst-utils.c | 25 +++++++++++++++++++++++
|
|
sound/soc/intel/skylake/skl-sst.c | 18 +++++++++++++++--
|
|
sound/soc/intel/skylake/skl.h | 14 -------------
|
|
9 files changed, 104 insertions(+), 39 deletions(-)
|
|
|
|
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c
|
|
index bac77f8fc0d4..76266d3945e7 100644
|
|
--- a/sound/soc/intel/skylake/bxt-sst.c
|
|
+++ b/sound/soc/intel/skylake/bxt-sst.c
|
|
@@ -311,6 +311,16 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
|
|
skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
|
|
ret = -EIO;
|
|
} else {
|
|
+ ret = skl_get_firmware_configuration(ctx);
|
|
+ if (ret < 0) {
|
|
+ dev_err(ctx->dev, "FW version query failed\n");
|
|
+ goto sst_load_base_firmware_failed;
|
|
+ }
|
|
+
|
|
+ ret = skl_validate_fw_version(skl);
|
|
+ if (ret < 0)
|
|
+ goto sst_load_base_firmware_failed;
|
|
+
|
|
ret = 0;
|
|
skl->fw_loaded = true;
|
|
}
|
|
@@ -632,21 +642,24 @@ static struct sst_dsp_device skl_dev = {
|
|
};
|
|
|
|
int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
struct skl_sst **dsp, void *ptr)
|
|
{
|
|
struct skl_sst *skl;
|
|
struct sst_dsp *sst;
|
|
+ struct skl_dsp_loader_ops loader_ops;
|
|
u32 dsp_wp[] = {BXT_ADSP_WP_DSP0, BXT_ADSP_WP_DSP1};
|
|
int ret;
|
|
|
|
- ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev);
|
|
+ loader_ops = dsp_ops->loader_ops();
|
|
+ ret = skl_sst_ctx_init(dev, irq, fw_name, loader_ops, dsp, &skl_dev);
|
|
if (ret < 0) {
|
|
dev_err(dev, "%s: no device\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
skl = *dsp;
|
|
+ skl->dsp_ops = dsp_ops;
|
|
sst = skl->dsp;
|
|
sst->fw_ops = bxt_fw_ops;
|
|
sst->addr.lpe = mmio_base;
|
|
diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h
|
|
index 5f0653b36308..7bc24ee5eecc 100644
|
|
--- a/sound/soc/intel/skylake/cnl-sst-dsp.h
|
|
+++ b/sound/soc/intel/skylake/cnl-sst-dsp.h
|
|
@@ -117,7 +117,7 @@ bool cnl_ipc_int_status(struct sst_dsp *ctx);
|
|
void cnl_ipc_free(struct sst_generic_ipc *ipc);
|
|
|
|
int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
struct skl_sst **dsp, void *ptr);
|
|
int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx);
|
|
void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
|
|
diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c
|
|
index 19398e200cb0..52565423c83e 100644
|
|
--- a/sound/soc/intel/skylake/cnl-sst.c
|
|
+++ b/sound/soc/intel/skylake/cnl-sst.c
|
|
@@ -273,6 +273,10 @@ static int cnl_load_base_firmware(struct sst_dsp *ctx)
|
|
goto load_base_firmware_failed;
|
|
}
|
|
|
|
+ ret = skl_validate_fw_version(cnl);
|
|
+ if (ret < 0)
|
|
+ goto load_base_firmware_failed;
|
|
+
|
|
fw_property = cnl->fw_property;
|
|
if (fw_property.memory_reclaimed <= 0) {
|
|
dev_err(ctx->dev, "Memory reclaim not enabled:%d\n",
|
|
@@ -725,22 +729,25 @@ static void skl_unregister_sdw_masters(struct skl_sst *ctx)
|
|
}
|
|
|
|
int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
struct skl_sst **dsp, void *ptr)
|
|
{
|
|
struct skl_sst *cnl;
|
|
struct sst_dsp *sst;
|
|
+ struct skl_dsp_loader_ops loader_ops;
|
|
u32 dsp_wp[] = {CNL_ADSP_WP_DSP0, CNL_ADSP_WP_DSP1, CNL_ADSP_WP_DSP2,
|
|
CNL_ADSP_WP_DSP3};
|
|
int ret;
|
|
|
|
- ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev);
|
|
+ loader_ops = dsp_ops->loader_ops();
|
|
+ ret = skl_sst_ctx_init(dev, irq, fw_name, loader_ops, dsp, &cnl_dev);
|
|
if (ret < 0) {
|
|
dev_err(dev, "%s: no device\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
cnl = *dsp;
|
|
+ cnl->dsp_ops = dsp_ops;
|
|
sst = cnl->dsp;
|
|
sst->fw_ops = cnl_fw_ops;
|
|
sst->addr.lpe = mmio_base;
|
|
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
|
|
index c01875a2a61d..f66ae9d702bc 100644
|
|
--- a/sound/soc/intel/skylake/skl-messages.c
|
|
+++ b/sound/soc/intel/skylake/skl-messages.c
|
|
@@ -277,7 +277,8 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
|
.loader_ops = skl_get_loader_ops,
|
|
.init = skl_sst_dsp_init,
|
|
.init_fw = skl_sst_init_fw,
|
|
- .cleanup = skl_sst_dsp_cleanup
|
|
+ .cleanup = skl_sst_dsp_cleanup,
|
|
+ .min_fw_ver = {9, 21, 0, 3173}
|
|
},
|
|
{
|
|
.id = 0x9d71,
|
|
@@ -285,7 +286,8 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
|
.loader_ops = skl_get_loader_ops,
|
|
.init = skl_sst_dsp_init,
|
|
.init_fw = skl_sst_init_fw,
|
|
- .cleanup = skl_sst_dsp_cleanup
|
|
+ .cleanup = skl_sst_dsp_cleanup,
|
|
+ .min_fw_ver = {9, 21, 0, 3173}
|
|
},
|
|
{
|
|
.id = 0x5a98,
|
|
@@ -294,7 +296,8 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
|
.init = bxt_sst_dsp_init,
|
|
.init_fw = bxt_sst_init_fw,
|
|
.cleanup = bxt_sst_dsp_cleanup,
|
|
- .do_recovery = skl_do_recovery
|
|
+ .do_recovery = skl_do_recovery,
|
|
+ .min_fw_ver = {9, 22, 1, 3132}
|
|
},
|
|
{
|
|
.id = 0x3198,
|
|
@@ -303,7 +306,8 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
|
.init = bxt_sst_dsp_init,
|
|
.init_fw = bxt_sst_init_fw,
|
|
.cleanup = bxt_sst_dsp_cleanup,
|
|
- .do_recovery = skl_do_recovery
|
|
+ .do_recovery = skl_do_recovery,
|
|
+ .min_fw_ver = {9, 22, 1, 3366}
|
|
},
|
|
{
|
|
.id = 0x9dc8,
|
|
@@ -312,7 +316,8 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
|
.init = cnl_sst_dsp_init,
|
|
.init_fw = cnl_sst_init_fw,
|
|
.cleanup = cnl_sst_dsp_cleanup,
|
|
- .do_recovery = skl_do_recovery
|
|
+ .do_recovery = skl_do_recovery,
|
|
+ .min_fw_ver = {10, 23, 0, 1233}
|
|
},
|
|
{
|
|
.id = 0x34c8,
|
|
@@ -321,7 +326,8 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
|
.init = cnl_sst_dsp_init,
|
|
.init_fw = cnl_sst_init_fw,
|
|
.cleanup = cnl_sst_dsp_cleanup,
|
|
- .do_recovery = skl_do_recovery
|
|
+ .do_recovery = skl_do_recovery,
|
|
+ .min_fw_ver = {10, 23, 0, 1233}
|
|
},
|
|
};
|
|
|
|
@@ -1283,14 +1289,12 @@ int skl_init_dsp(struct skl *skl)
|
|
goto unmap_mmio;
|
|
}
|
|
|
|
- loader_ops = ops->loader_ops();
|
|
- ret = ops->init(bus->dev, mmio_base, irq, skl->fw_name, loader_ops,
|
|
+ ret = ops->init(bus->dev, mmio_base, irq, skl->fw_name, ops,
|
|
&skl->skl_sst, &cnl_sdw_bra_ops);
|
|
|
|
if (ret < 0)
|
|
goto unmap_mmio;
|
|
|
|
- skl->skl_sst->dsp_ops = ops;
|
|
cores = &skl->skl_sst->cores;
|
|
cores->count = ops->num_cores;
|
|
|
|
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
|
|
index dc793d503115..fa3a47183916 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
|
|
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
|
|
@@ -178,6 +178,13 @@ enum skl_hw_info_type {
|
|
SKL_EBB_SIZE_BYTES,
|
|
};
|
|
|
|
+struct skl_fw_version {
|
|
+ u16 major;
|
|
+ u16 minor;
|
|
+ u16 hotfix;
|
|
+ u16 build;
|
|
+};
|
|
+
|
|
/* DSP Core state */
|
|
enum skl_dsp_states {
|
|
SKL_DSP_RUNNING = 1,
|
|
@@ -193,6 +200,19 @@ enum skl_dsp_d0i3_states {
|
|
SKL_DSP_D0I3_STREAMING = 1,
|
|
};
|
|
|
|
+struct skl_dsp_ops {
|
|
+ int id;
|
|
+ unsigned int num_cores;
|
|
+ struct skl_dsp_loader_ops (*loader_ops)(void);
|
|
+ struct skl_fw_version min_fw_ver;
|
|
+ int (*init)(struct device *dev, void __iomem *mmio_base, int irq,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
+ struct skl_sst **skl_sst, void *ptr);
|
|
+ int (*init_fw)(struct device *dev, struct skl_sst *ctx);
|
|
+ void (*cleanup)(struct device *dev, struct skl_sst *ctx);
|
|
+ void (*do_recovery)(struct skl *skl);
|
|
+};
|
|
+
|
|
struct skl_dsp_fw_ops {
|
|
int (*load_fw)(struct sst_dsp *ctx);
|
|
/* FW module parser/loader */
|
|
@@ -294,10 +314,10 @@ int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id);
|
|
|
|
int skl_dsp_boot(struct sst_dsp *ctx);
|
|
int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
struct skl_sst **dsp, void *ptr);
|
|
int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
struct skl_sst **dsp, void *ptr);
|
|
int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx);
|
|
int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx);
|
|
@@ -331,6 +351,8 @@ void skl_release_library(struct skl_lib_info *linfo, int lib_count);
|
|
int skl_get_firmware_configuration(struct sst_dsp *ctx);
|
|
int skl_get_hardware_configuration(struct sst_dsp *ctx);
|
|
|
|
+int skl_validate_fw_version(struct skl_sst *skl);
|
|
+
|
|
int bxt_set_dsp_D0i0(struct sst_dsp *ctx);
|
|
|
|
int bxt_schedule_dsp_D0i3(struct sst_dsp *ctx);
|
|
@@ -344,4 +366,5 @@ void skl_module_sysfs_exit(struct skl_sst *ctx);
|
|
int skl_dsp_cb_event(struct skl_sst *ctx, unsigned int event,
|
|
struct skl_notify_data *notify_data);
|
|
|
|
+const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id);
|
|
#endif /*__SKL_SST_DSP_H__*/
|
|
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
|
|
index ee32aaa68490..4eef4a386996 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
|
|
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
|
|
@@ -152,13 +152,6 @@ struct bra_conf {
|
|
struct skl_pipe *cp_pipe;
|
|
};
|
|
|
|
-struct skl_fw_version {
|
|
- u16 major;
|
|
- u16 minor;
|
|
- u16 hotfix;
|
|
- u16 build;
|
|
-};
|
|
-
|
|
struct skl_dma_buff_config {
|
|
u32 min_size_bytes;
|
|
u32 max_size_bytes;
|
|
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c
|
|
index 7c867426b39b..a495cea49b05 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst-utils.c
|
|
+++ b/sound/soc/intel/skylake/skl-sst-utils.c
|
|
@@ -1246,3 +1246,28 @@ int skl_module_sysfs_init(struct skl_sst *ctx, struct kobject *kobj)
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(skl_module_sysfs_init);
|
|
+
|
|
+int skl_validate_fw_version(struct skl_sst *skl)
|
|
+{
|
|
+ struct skl_fw_version *fw_version = &skl->fw_property.version;
|
|
+ const struct skl_dsp_ops *ops = skl->dsp_ops;
|
|
+
|
|
+ dev_info(skl->dev, "ADSP FW Version: %d.%d.%d.%d\n",
|
|
+ fw_version->major, fw_version->minor,
|
|
+ fw_version->hotfix, fw_version->build);
|
|
+
|
|
+
|
|
+ if (ops->min_fw_ver.major == fw_version->major &&
|
|
+ ops->min_fw_ver.minor == fw_version->minor &&
|
|
+ ops->min_fw_ver.hotfix == fw_version->hotfix &&
|
|
+ ops->min_fw_ver.build <= fw_version->build)
|
|
+ return 0;
|
|
+
|
|
+ dev_err(skl->dev, "Incorrect ADSP FW version = %d.%d.%d.%d, minimum supported FW version = %d.%d.%d.%d\n",
|
|
+ fw_version->major, fw_version->minor,
|
|
+ fw_version->hotfix, fw_version->build,
|
|
+ ops->min_fw_ver.major, ops->min_fw_ver.minor,
|
|
+ ops->min_fw_ver.hotfix, ops->min_fw_ver.build);
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c
|
|
index 277e972eb858..77cf3f2ba95f 100644
|
|
--- a/sound/soc/intel/skylake/skl-sst.c
|
|
+++ b/sound/soc/intel/skylake/skl-sst.c
|
|
@@ -152,6 +152,17 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
|
|
goto transfer_firmware_failed;
|
|
}
|
|
|
|
+ ret = skl_get_firmware_configuration(ctx);
|
|
+ if (ret < 0) {
|
|
+ dev_err(ctx->dev, "FW version query failed\n");
|
|
+ goto skl_load_base_firmware_failed;
|
|
+ }
|
|
+
|
|
+ ret = skl_validate_fw_version(skl);
|
|
+ if (ret < 0) {
|
|
+ ret = -EIO;
|
|
+ goto skl_load_base_firmware_failed;
|
|
+ }
|
|
dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
|
|
skl->fw_loaded = true;
|
|
}
|
|
@@ -528,20 +539,23 @@ static struct sst_dsp_device skl_dev = {
|
|
};
|
|
|
|
int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
|
|
+ const char *fw_name, const struct skl_dsp_ops *dsp_ops,
|
|
struct skl_sst **dsp, void *ptr)
|
|
{
|
|
struct skl_sst *skl;
|
|
struct sst_dsp *sst;
|
|
+ struct skl_dsp_loader_ops loader_ops;
|
|
int ret;
|
|
|
|
- ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev);
|
|
+ loader_ops = dsp_ops->loader_ops();
|
|
+ ret = skl_sst_ctx_init(dev, irq, fw_name, loader_ops, dsp, &skl_dev);
|
|
if (ret < 0) {
|
|
dev_err(dev, "%s: no device\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
skl = *dsp;
|
|
+ skl->dsp_ops = dsp_ops;
|
|
sst = skl->dsp;
|
|
sst->addr.lpe = mmio_base;
|
|
sst->addr.shim = mmio_base;
|
|
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
|
|
index 01053c4cdf6e..d00a8b19d054 100644
|
|
--- a/sound/soc/intel/skylake/skl.h
|
|
+++ b/sound/soc/intel/skylake/skl.h
|
|
@@ -188,19 +188,6 @@ struct skl_machine_pdata {
|
|
bool use_tplg_pcm; /* use dais and dai links from topology */
|
|
};
|
|
|
|
-struct skl_dsp_ops {
|
|
- int id;
|
|
- unsigned int num_cores;
|
|
- struct skl_dsp_loader_ops (*loader_ops)(void);
|
|
- int (*init)(struct device *dev, void __iomem *mmio_base, int irq,
|
|
- const char *fw_name,
|
|
- struct skl_dsp_loader_ops loader_ops,
|
|
- struct skl_sst **skl_sst, void *ptr);
|
|
- int (*init_fw)(struct device *dev, struct skl_sst *ctx);
|
|
- void (*cleanup)(struct device *dev, struct skl_sst *ctx);
|
|
- void (*do_recovery)(struct skl *skl);
|
|
-};
|
|
-
|
|
int skl_platform_unregister(struct device *dev);
|
|
int skl_platform_register(struct device *dev);
|
|
|
|
@@ -223,7 +210,6 @@ int skl_suspend_late_dsp(struct skl *skl);
|
|
int skl_suspend_dsp(struct skl *skl);
|
|
int skl_resume_dsp(struct skl *skl);
|
|
void skl_cleanup_resources(struct skl *skl);
|
|
-const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id);
|
|
void skl_update_d0i3c(struct device *dev, bool enable);
|
|
int skl_nhlt_create_sysfs(struct skl *skl);
|
|
void skl_nhlt_remove_sysfs(struct skl *skl);
|
|
--
|
|
2.19.1
|
|
|