ASoC: SOF: topology: add support for stricter ABI checks
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Tue, 30 Apr 2019 23:09:18 +0000 (18:09 -0500)
committerMark Brown <broonie@kernel.org>
Fri, 3 May 2019 05:56:31 +0000 (14:56 +0900)
Fail early if topology is more recent than kernel and Kconfig is
selected.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/topology.c

index 1f71857..c88afa8 100644 (file)
@@ -3049,6 +3049,7 @@ static int sof_manifest(struct snd_soc_component *scomp, int index,
 {
        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
        u32 size;
+       u32 abi_version;
 
        size = le32_to_cpu(man->priv.size);
 
@@ -3058,20 +3059,36 @@ static int sof_manifest(struct snd_soc_component *scomp, int index,
                return 0;
        }
 
-       if (size == SOF_TPLG_ABI_SIZE) {
-               dev_info(sdev->dev,
-                        "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
-                        man->priv.data[0], man->priv.data[1],
-                        man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR,
-                        SOF_ABI_PATCH);
-               if (SOF_ABI_VER(man->priv.data[0], man->priv.data[1],
-                               man->priv.data[2]) <= SOF_ABI_VERSION)
-                       return 0;
+       if (size != SOF_TPLG_ABI_SIZE) {
+               dev_err(sdev->dev, "error: invalid topology ABI size\n");
+               return -EINVAL;
        }
-       dev_err(sdev->dev,
-               "error: Incompatible ABI version %d:%d:%d\n",
-               man->priv.data[0], man->priv.data[1], man->priv.data[2]);
-       return -EINVAL;
+
+       dev_info(sdev->dev,
+                "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
+                man->priv.data[0], man->priv.data[1],
+                man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR,
+                SOF_ABI_PATCH);
+
+       abi_version = SOF_ABI_VER(man->priv.data[0],
+                                 man->priv.data[1],
+                                 man->priv.data[2]);
+
+       if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) {
+               dev_err(sdev->dev, "error: incompatible topology ABI version\n");
+               return -EINVAL;
+       }
+
+       if (abi_version > SOF_ABI_VERSION) {
+               if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
+                       dev_warn(sdev->dev, "warn: topology ABI is more recent than kernel\n");
+               } else {
+                       dev_err(sdev->dev, "error: topology ABI is more recent than kernel\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
 }
 
 /* vendor specific kcontrol handlers available for binding */