Skip to content

Commit

Permalink
ALSA: hda: hda_component: Protect shared data with a mutex
Browse files Browse the repository at this point in the history
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: Simon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/20240617154105.108635-5-simont@opensource.cirrus.com
  • Loading branch information
Simon Trimmer authored and Takashi Iwai committed Jun 18, 2024
1 parent 3b2a858 commit 047b9cb
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
13 changes: 12 additions & 1 deletion sound/pci/hda/hda_component.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ void hda_component_acpi_device_notify(struct hda_component_parent *parent,
struct hda_component *comp;
int i;

mutex_lock(&parent->mutex);
for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
comp = hda_component_from_index(parent, i);
if (comp->dev && comp->acpi_notify)
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);

Expand Down Expand Up @@ -87,6 +89,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in
struct hda_component *comp;
int i;

mutex_lock(&parent->mutex);
for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
comp = hda_component_from_index(parent, i);
if (comp->dev && comp->pre_playback_hook)
Expand All @@ -102,6 +105,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in
if (comp->dev && comp->post_playback_hook)
comp->post_playback_hook(comp->dev, action);
}
mutex_unlock(&parent->mutex);
}
EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, SND_HDA_SCODEC_COMPONENT);

Expand Down Expand Up @@ -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,
struct hda_component_parent *parent)
{
int ret;

/* Init shared and component specific data */
memset(parent, 0, sizeof(*parent));
mutex_init(&parent->mutex);
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);

Expand Down
4 changes: 4 additions & 0 deletions sound/pci/hda/hda_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <linux/acpi.h>
#include <linux/component.h>
#include <linux/mutex.h>
#include <sound/hda_codec.h>

#define HDA_MAX_COMPONENTS 4
Expand All @@ -28,6 +29,7 @@ struct hda_component {
};

struct hda_component_parent {
struct mutex mutex;
struct hda_codec *codec;
struct hda_component comps[HDA_MAX_COMPONENTS];
};
Expand Down Expand Up @@ -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,
struct hda_component_parent *parent)
{
mutex_lock(&parent->mutex);
component_unbind_all(hda_codec_dev(cdc), parent);
mutex_unlock(&parent->mutex);
}

#endif /* ifndef __HDA_COMPONENT_H__ */

0 comments on commit 047b9cb

Please sign in to comment.