Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3335ddca authored by Dimitris Papastamos's avatar Dimitris Papastamos Committed by Mark Brown
Browse files

ASoC: soc-cache: Use reg_def_copy instead of reg_cache_default



Make sure to use codec->reg_def_copy instead of codec_drv->reg_cache_default
wherever necessary.  This change is necessary because in the next patch we
move the cache initialization code outside snd_soc_register_codec() and by that
time any data marked as __devinitconst such as the original reg_cache_default
array might have already been freed by the kernel.

Signed-off-by: default avatarDimitris Papastamos <dp@opensource.wolfsonmicro.com>
Acked-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent ff819b83
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -480,6 +480,7 @@ struct snd_soc_codec {
	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
	void *reg_cache;
	const void *reg_def_copy;
	const struct snd_soc_cache_ops *cache_ops;
	struct mutex cache_rw_mutex;

+24 −12
Original line number Diff line number Diff line
@@ -933,7 +933,7 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
	rbtree_ctx = codec->reg_cache;
	rbtree_ctx->root = RB_ROOT;

	if (!codec->driver->reg_cache_default)
	if (!codec->reg_def_copy)
		return 0;

/*
@@ -951,7 +951,7 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
	struct snd_soc_rbtree_node *rbtree_node;			\
									\
	ret = 0;							\
	cache = codec->driver->reg_cache_default;			\
	cache = codec->reg_def_copy;					\
	for (i = 0; i < codec->driver->reg_cache_size; ++i) {		\
		if (!cache[i])						\
			continue;					\
@@ -1316,13 +1316,13 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
	 * and remember to free it afterwards.
	 */
	tofree = 0;
	if (!codec_drv->reg_cache_default)
	if (!codec->reg_def_copy)
		tofree = 1;

	if (!codec_drv->reg_cache_default) {
		codec_drv->reg_cache_default = kzalloc(reg_size,
	if (!codec->reg_def_copy) {
		codec->reg_def_copy = kzalloc(reg_size,
						       GFP_KERNEL);
		if (!codec_drv->reg_cache_default)
		if (!codec->reg_def_copy)
			return -ENOMEM;
	}

@@ -1368,8 +1368,8 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
	}

	blksize = snd_soc_lzo_get_blksize(codec);
	p = codec_drv->reg_cache_default;
	end = codec_drv->reg_cache_default + reg_size;
	p = codec->reg_def_copy;
	end = codec->reg_def_copy + reg_size;
	/* compress the register map and fill the lzo blocks */
	for (i = 0; i < blkcount; ++i, p += blksize) {
		lzo_blocks[i]->src = p;
@@ -1385,14 +1385,18 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
			lzo_blocks[i]->src_len;
	}

	if (tofree)
		kfree(codec_drv->reg_cache_default);
	if (tofree) {
		kfree(codec->reg_def_copy);
		codec->reg_def_copy = NULL;
	}
	return 0;
err:
	snd_soc_cache_exit(codec);
err_tofree:
	if (tofree)
		kfree(codec_drv->reg_cache_default);
	if (tofree) {
		kfree(codec->reg_def_copy);
		codec->reg_def_copy = NULL;
	}
	return ret;
}

@@ -1506,6 +1510,14 @@ static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
	codec_drv = codec->driver;
	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;

	/*
	 * for flat compression, we don't need to keep a copy of the
	 * original defaults register cache as it will definitely not
	 * be marked as __devinitconst
	 */
	kfree(codec->reg_def_copy);
	codec->reg_def_copy = NULL;

	if (codec_drv->reg_cache_default)
		codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
					   reg_size, GFP_KERNEL);
+17 −0
Original line number Diff line number Diff line
@@ -3434,6 +3434,7 @@ int snd_soc_register_codec(struct device *dev,
		struct snd_soc_codec_driver *codec_drv,
		struct snd_soc_dai_driver *dai_drv, int num_dai)
{
	size_t reg_size;
	struct snd_soc_codec *codec;
	int ret, i;

@@ -3469,6 +3470,19 @@ int snd_soc_register_codec(struct device *dev,

	/* allocate CODEC register cache */
	if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
		reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
		/* it is necessary to make a copy of the default register cache
		 * because in the case of using a compression type that requires
		 * the default register cache to be marked as __devinitconst the
		 * kernel might have freed the array by the time we initialize
		 * the cache.
		 */
		codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
					      reg_size, GFP_KERNEL);
		if (!codec->reg_def_copy) {
			ret = -ENOMEM;
			goto error_cache;
		}
		ret = snd_soc_cache_init(codec);
		if (ret < 0) {
			dev_err(codec->dev, "Failed to set cache compression type: %d\n",
@@ -3500,6 +3514,8 @@ int snd_soc_register_codec(struct device *dev,
error_dais:
	snd_soc_cache_exit(codec);
error_cache:
	kfree(codec->reg_def_copy);
	codec->reg_def_copy = NULL;
	kfree(codec->name);
	kfree(codec);
	return ret;
@@ -3534,6 +3550,7 @@ void snd_soc_unregister_codec(struct device *dev)
	pr_debug("Unregistered codec '%s'\n", codec->name);

	snd_soc_cache_exit(codec);
	kfree(codec->reg_def_copy);
	kfree(codec->name);
	kfree(codec);
}