Commit 047b9cbb authored by Simon Trimmer's avatar Simon Trimmer Committed by Takashi Iwai

ALSA: hda: hda_component: Protect shared data with a mutex

The hda_component contains information shared from the amp drivers to
the codec that can be altered (for example as the driver unloads). Guard
the update and use of these to prevent use of stale data.
Signed-off-by: default avatarSimon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/20240617154105.108635-5-simont@opensource.cirrus.com
parent 3b2a8582
...@@ -21,11 +21,13 @@ void hda_component_acpi_device_notify(struct hda_component_parent *parent, ...@@ -21,11 +21,13 @@ void hda_component_acpi_device_notify(struct hda_component_parent *parent,
struct hda_component *comp; struct hda_component *comp;
int i; int i;
mutex_lock(&parent->mutex);
for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
comp = hda_component_from_index(parent, i); comp = hda_component_from_index(parent, i);
if (comp->dev && comp->acpi_notify) if (comp->dev && comp->acpi_notify)
comp->acpi_notify(acpi_device_handle(comp->adev), event, comp->dev); comp->acpi_notify(acpi_device_handle(comp->adev), event, comp->dev);
} }
mutex_unlock(&parent->mutex);
} }
EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, SND_HDA_SCODEC_COMPONENT); EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, SND_HDA_SCODEC_COMPONENT);
...@@ -87,6 +89,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in ...@@ -87,6 +89,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in
struct hda_component *comp; struct hda_component *comp;
int i; int i;
mutex_lock(&parent->mutex);
for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
comp = hda_component_from_index(parent, i); comp = hda_component_from_index(parent, i);
if (comp->dev && comp->pre_playback_hook) if (comp->dev && comp->pre_playback_hook)
...@@ -102,6 +105,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in ...@@ -102,6 +105,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in
if (comp->dev && comp->post_playback_hook) if (comp->dev && comp->post_playback_hook)
comp->post_playback_hook(comp->dev, action); comp->post_playback_hook(comp->dev, action);
} }
mutex_unlock(&parent->mutex);
} }
EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, SND_HDA_SCODEC_COMPONENT); EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, SND_HDA_SCODEC_COMPONENT);
...@@ -134,11 +138,18 @@ static int hda_comp_match_dev_name(struct device *dev, void *data) ...@@ -134,11 +138,18 @@ static int hda_comp_match_dev_name(struct device *dev, void *data)
int hda_component_manager_bind(struct hda_codec *cdc, int hda_component_manager_bind(struct hda_codec *cdc,
struct hda_component_parent *parent) struct hda_component_parent *parent)
{ {
int ret;
/* Init shared and component specific data */ /* Init shared and component specific data */
memset(parent, 0, sizeof(*parent)); memset(parent, 0, sizeof(*parent));
mutex_init(&parent->mutex);
parent->codec = cdc; parent->codec = cdc;
return component_bind_all(hda_codec_dev(cdc), parent); mutex_lock(&parent->mutex);
ret = component_bind_all(hda_codec_dev(cdc), parent);
mutex_unlock(&parent->mutex);
return ret;
} }
EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, SND_HDA_SCODEC_COMPONENT); EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, SND_HDA_SCODEC_COMPONENT);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/mutex.h>
#include <sound/hda_codec.h> #include <sound/hda_codec.h>
#define HDA_MAX_COMPONENTS 4 #define HDA_MAX_COMPONENTS 4
...@@ -28,6 +29,7 @@ struct hda_component { ...@@ -28,6 +29,7 @@ struct hda_component {
}; };
struct hda_component_parent { struct hda_component_parent {
struct mutex mutex;
struct hda_codec *codec; struct hda_codec *codec;
struct hda_component comps[HDA_MAX_COMPONENTS]; struct hda_component comps[HDA_MAX_COMPONENTS];
}; };
...@@ -93,7 +95,9 @@ static inline struct hda_component *hda_component_from_index(struct hda_componen ...@@ -93,7 +95,9 @@ static inline struct hda_component *hda_component_from_index(struct hda_componen
static inline void hda_component_manager_unbind(struct hda_codec *cdc, static inline void hda_component_manager_unbind(struct hda_codec *cdc,
struct hda_component_parent *parent) struct hda_component_parent *parent)
{ {
mutex_lock(&parent->mutex);
component_unbind_all(hda_codec_dev(cdc), parent); component_unbind_all(hda_codec_dev(cdc), parent);
mutex_unlock(&parent->mutex);
} }
#endif /* ifndef __HDA_COMPONENT_H__ */ #endif /* ifndef __HDA_COMPONENT_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment