aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-04-21 17:49:11 +0200
committerSasha Levin <sasha.levin@oracle.com>2016-07-10 20:19:59 -0400
commitec3e73223a8e5a5ec66ca6a2b12d37ddaf2530dd (patch)
tree27adffae618b7b6d5c32e1bcd0e5d63613813783 /include
parentc262505cdb45765ddea20a1f85f0023990276772 (diff)
ALSA: hda - Fix possible race on regmap bypass flip
[ Upstream commit 3194ed497939c6448005542e3ca4fa2386968fa0 ] HD-audio driver uses regmap cache bypass feature for reading a raw value without the cache. But this is racy since both the cached and the uncached reads may occur concurrently. The former is done via the normal control API access while the latter comes from the proc file read. Even though the regmap itself has the protection against the concurrent accesses, the flag set/reset is done without the protection, so it may lead to inconsistent state of bypass flag that doesn't match with the current read and occasionally result in a kernel WARNING like: WARNING: CPU: 3 PID: 2731 at drivers/base/regmap/regcache.c:499 regcache_cache_only+0x78/0x93 One way to work around such a problem is to wrap with a mutex. But in this case, the solution is simpler: for the uncached read, we just skip the regmap and directly calls its accessor. The verb execution there is protected by itself, so basically it's safe to call individually. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=116171 Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'include')
-rw-r--r--include/sound/hda_regmap.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/sound/hda_regmap.h b/include/sound/hda_regmap.h
index df705908480a..2f48d648e051 100644
--- a/include/sound/hda_regmap.h
+++ b/include/sound/hda_regmap.h
@@ -17,6 +17,8 @@ int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec,
unsigned int verb);
int snd_hdac_regmap_read_raw(struct hdac_device *codec, unsigned int reg,
unsigned int *val);
+int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec,
+ unsigned int reg, unsigned int *val);
int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
unsigned int val);
int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,