forked from Minki/linux
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: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
ff819b8357
commit
3335ddca93
@ -480,6 +480,7 @@ struct snd_soc_codec {
|
|||||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||||
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||||
void *reg_cache;
|
void *reg_cache;
|
||||||
|
const void *reg_def_copy;
|
||||||
const struct snd_soc_cache_ops *cache_ops;
|
const struct snd_soc_cache_ops *cache_ops;
|
||||||
struct mutex cache_rw_mutex;
|
struct mutex cache_rw_mutex;
|
||||||
|
|
||||||
|
@ -933,7 +933,7 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
|
|||||||
rbtree_ctx = codec->reg_cache;
|
rbtree_ctx = codec->reg_cache;
|
||||||
rbtree_ctx->root = RB_ROOT;
|
rbtree_ctx->root = RB_ROOT;
|
||||||
|
|
||||||
if (!codec->driver->reg_cache_default)
|
if (!codec->reg_def_copy)
|
||||||
return 0;
|
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; \
|
struct snd_soc_rbtree_node *rbtree_node; \
|
||||||
\
|
\
|
||||||
ret = 0; \
|
ret = 0; \
|
||||||
cache = codec->driver->reg_cache_default; \
|
cache = codec->reg_def_copy; \
|
||||||
for (i = 0; i < codec->driver->reg_cache_size; ++i) { \
|
for (i = 0; i < codec->driver->reg_cache_size; ++i) { \
|
||||||
if (!cache[i]) \
|
if (!cache[i]) \
|
||||||
continue; \
|
continue; \
|
||||||
@ -1316,13 +1316,13 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
|
|||||||
* and remember to free it afterwards.
|
* and remember to free it afterwards.
|
||||||
*/
|
*/
|
||||||
tofree = 0;
|
tofree = 0;
|
||||||
if (!codec_drv->reg_cache_default)
|
if (!codec->reg_def_copy)
|
||||||
tofree = 1;
|
tofree = 1;
|
||||||
|
|
||||||
if (!codec_drv->reg_cache_default) {
|
if (!codec->reg_def_copy) {
|
||||||
codec_drv->reg_cache_default = kzalloc(reg_size,
|
codec->reg_def_copy = kzalloc(reg_size,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!codec_drv->reg_cache_default)
|
if (!codec->reg_def_copy)
|
||||||
return -ENOMEM;
|
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);
|
blksize = snd_soc_lzo_get_blksize(codec);
|
||||||
p = codec_drv->reg_cache_default;
|
p = codec->reg_def_copy;
|
||||||
end = codec_drv->reg_cache_default + reg_size;
|
end = codec->reg_def_copy + reg_size;
|
||||||
/* compress the register map and fill the lzo blocks */
|
/* compress the register map and fill the lzo blocks */
|
||||||
for (i = 0; i < blkcount; ++i, p += blksize) {
|
for (i = 0; i < blkcount; ++i, p += blksize) {
|
||||||
lzo_blocks[i]->src = p;
|
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;
|
lzo_blocks[i]->src_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tofree)
|
if (tofree) {
|
||||||
kfree(codec_drv->reg_cache_default);
|
kfree(codec->reg_def_copy);
|
||||||
|
codec->reg_def_copy = NULL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
snd_soc_cache_exit(codec);
|
snd_soc_cache_exit(codec);
|
||||||
err_tofree:
|
err_tofree:
|
||||||
if (tofree)
|
if (tofree) {
|
||||||
kfree(codec_drv->reg_cache_default);
|
kfree(codec->reg_def_copy);
|
||||||
|
codec->reg_def_copy = NULL;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1506,6 +1510,14 @@ static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
|
|||||||
codec_drv = codec->driver;
|
codec_drv = codec->driver;
|
||||||
reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
|
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)
|
if (codec_drv->reg_cache_default)
|
||||||
codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
|
codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
|
||||||
reg_size, GFP_KERNEL);
|
reg_size, GFP_KERNEL);
|
||||||
|
@ -3434,6 +3434,7 @@ int snd_soc_register_codec(struct device *dev,
|
|||||||
struct snd_soc_codec_driver *codec_drv,
|
struct snd_soc_codec_driver *codec_drv,
|
||||||
struct snd_soc_dai_driver *dai_drv, int num_dai)
|
struct snd_soc_dai_driver *dai_drv, int num_dai)
|
||||||
{
|
{
|
||||||
|
size_t reg_size;
|
||||||
struct snd_soc_codec *codec;
|
struct snd_soc_codec *codec;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
@ -3469,6 +3470,19 @@ int snd_soc_register_codec(struct device *dev,
|
|||||||
|
|
||||||
/* allocate CODEC register cache */
|
/* allocate CODEC register cache */
|
||||||
if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
|
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);
|
ret = snd_soc_cache_init(codec);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(codec->dev, "Failed to set cache compression type: %d\n",
|
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:
|
error_dais:
|
||||||
snd_soc_cache_exit(codec);
|
snd_soc_cache_exit(codec);
|
||||||
error_cache:
|
error_cache:
|
||||||
|
kfree(codec->reg_def_copy);
|
||||||
|
codec->reg_def_copy = NULL;
|
||||||
kfree(codec->name);
|
kfree(codec->name);
|
||||||
kfree(codec);
|
kfree(codec);
|
||||||
return ret;
|
return ret;
|
||||||
@ -3534,6 +3550,7 @@ found:
|
|||||||
pr_debug("Unregistered codec '%s'\n", codec->name);
|
pr_debug("Unregistered codec '%s'\n", codec->name);
|
||||||
|
|
||||||
snd_soc_cache_exit(codec);
|
snd_soc_cache_exit(codec);
|
||||||
|
kfree(codec->reg_def_copy);
|
||||||
kfree(codec->name);
|
kfree(codec->name);
|
||||||
kfree(codec);
|
kfree(codec);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user