[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