[PATCH] [RFC] ALSA: hda: add locking to regcache calls

Kai Vehmanen kai.vehmanen at linux.intel.com
Tue Jan 7 16:48:40 UTC 2020


From: Takashi Iwai <tiwai at suse.de>

Cc: Kai Vehmanen <kai.vehmanen at linux.intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/issues/592
---
 include/sound/hdaudio.h       | 1 +
 sound/hda/hdac_device.c       | 1 +
 sound/pci/hda/hda_codec.c     | 5 +++--
 sound/pci/hda/hda_generic.c   | 2 +-
 sound/pci/hda/hda_local.h     | 9 +++++++++
 sound/pci/hda/patch_hdmi.c    | 2 +-
 sound/pci/hda/patch_realtek.c | 4 ++--
 sound/pci/hda/patch_via.c     | 2 +-
 8 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index bc2f77a6f17b..541ca99b154b 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -86,6 +86,7 @@ struct hdac_device {
 
 	/* regmap */
 	struct regmap *regmap;
+	struct mutex regmap_lock;
 	struct snd_array vendor_verbs;
 	bool lazy_cache:1;	/* don't wake up for writes */
 	bool caps_overwriting:1; /* caps overwrite being in process */
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index 9f3e37511408..c946fd8beebc 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -57,6 +57,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
 	codec->addr = addr;
 	codec->type = HDA_DEV_CORE;
 	mutex_init(&codec->widget_lock);
+	mutex_init(&codec->regmap_lock);
 	pm_runtime_set_active(&codec->dev);
 	pm_runtime_get_noresume(&codec->dev);
 	atomic_set(&codec->in_pm, 0);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index a2fb19129219..2eed3eba2c12 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1339,9 +1339,11 @@ int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
 
 	if (!codec->core.regmap)
 		return -EINVAL;
+	mutex_lock(&codec->core.regmap_lock);
 	regcache_cache_only(codec->core.regmap, true);
 	orig = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
 	regcache_cache_only(codec->core.regmap, false);
+	mutex_unlock(&codec->core.regmap_lock);
 	if (orig >= 0)
 		return 0;
 	return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val);
@@ -2905,8 +2907,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
 	else {
 		if (codec->patch_ops.init)
 			codec->patch_ops.init(codec);
-		if (codec->core.regmap)
-			regcache_sync(codec->core.regmap);
+		snd_hda_regcache_sync(codec);
 	}
 
 	if (codec->jackpoll_interval)
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 10d502328b76..a98a78c59c33 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -6027,7 +6027,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
 	/* call init functions of standard auto-mute helpers */
 	update_automute_all(codec);
 
-	regcache_sync(codec->core.regmap);
+	snd_hda_regcache_sync(codec);
 
 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 3942e1b528d8..07853e37ae59 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -715,6 +715,15 @@ void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
 #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
 
+static inline void snd_hda_regcache_sync(struct hda_codec *codec)
+{
+	if (codec->core.regmap) {
+		mutex_lock(&codec->core.regmap_lock);
+		regcache_sync(codec->core.regmap);
+		mutex_unlock(&codec->core.regmap_lock);
+	}
+}
+
 /*
  */
 #define codec_err(codec, fmt, args...) \
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 630b1f5c276d..3fc640c5a8e7 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -2403,7 +2403,7 @@ static int generic_hdmi_resume(struct hda_codec *codec)
 	int pin_idx;
 
 	codec->patch_ops.init(codec);
-	regcache_sync(codec->core.regmap);
+	snd_hda_regcache_sync(codec);
 
 	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 		struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index dbfafee97931..a5e9e01b48ca 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -904,7 +904,7 @@ static int alc_resume(struct hda_codec *codec)
 	if (!spec->no_depop_delay)
 		msleep(150); /* to avoid pop noise */
 	codec->patch_ops.init(codec);
-	regcache_sync(codec->core.regmap);
+	snd_hda_regcache_sync(codec);
 	hda_call_check_power_status(codec, 0x01);
 	return 0;
 }
@@ -3634,7 +3634,7 @@ static int alc269_resume(struct hda_codec *codec)
 		msleep(200);
 	}
 
-	regcache_sync(codec->core.regmap);
+	snd_hda_regcache_sync(codec);
 	hda_call_check_power_status(codec, 0x01);
 
 	/* on some machine, the BIOS will clear the codec gpio data when enter
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 29dcdb8b36db..b24919e4b22a 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -396,7 +396,7 @@ static int via_resume(struct hda_codec *codec)
 	/* some delay here to make jack detection working (bko#98921) */
 	msleep(10);
 	codec->patch_ops.init(codec);
-	regcache_sync(codec->core.regmap);
+	snd_hda_regcache_sync(codec);
 	return 0;
 }
 #endif
-- 
2.17.1



More information about the Intel-gfx-trybot mailing list