diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-01-30 06:27:43 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-02-06 03:56:33 -0500 |
commit | 6bbc7fed849597ec35ffdcaf677910dd11d71d08 (patch) | |
tree | 570560b9981f146249c09fbcd8bde9cca8f3fc64 | |
parent | 4227de2a7e5f0ff6a58e919a9c4f2bb06e882f48 (diff) |
ALSA: Add a helper to add a new attribute group to card
For assigning sysfs entries for a card device from the driver,
introduce a new helper function, snd_card_add_dev_attr(). In this
way, we can avoid the possible race between the device registration
and the sysfs addition / removal.
The driver can pass a new attribute group to add freely. This has to
be called before snd_card_register().
Currently, up to two extra groups can be added. More than that, it'll
return an error.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | include/sound/core.h | 3 | ||||
-rw-r--r-- | sound/core/init.c | 31 |
2 files changed, 28 insertions, 6 deletions
diff --git a/include/sound/core.h b/include/sound/core.h index 58882bfacdd7..da5748289968 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -132,6 +132,7 @@ struct snd_card { | |||
132 | struct completion *release_completion; | 132 | struct completion *release_completion; |
133 | struct device *dev; /* device assigned to this card */ | 133 | struct device *dev; /* device assigned to this card */ |
134 | struct device card_dev; /* cardX object for sysfs */ | 134 | struct device card_dev; /* cardX object for sysfs */ |
135 | const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */ | ||
135 | bool registered; /* card_dev is registered? */ | 136 | bool registered; /* card_dev is registered? */ |
136 | 137 | ||
137 | #ifdef CONFIG_PM | 138 | #ifdef CONFIG_PM |
@@ -262,6 +263,8 @@ void snd_card_set_id(struct snd_card *card, const char *id); | |||
262 | int snd_card_register(struct snd_card *card); | 263 | int snd_card_register(struct snd_card *card); |
263 | int snd_card_info_init(void); | 264 | int snd_card_info_init(void); |
264 | int snd_card_info_done(void); | 265 | int snd_card_info_done(void); |
266 | int snd_card_add_dev_attr(struct snd_card *card, | ||
267 | const struct attribute_group *group); | ||
265 | int snd_component_add(struct snd_card *card, const char *component); | 268 | int snd_component_add(struct snd_card *card, const char *component); |
266 | int snd_card_file_add(struct snd_card *card, struct file *file); | 269 | int snd_card_file_add(struct snd_card *card, struct file *file); |
267 | int snd_card_file_remove(struct snd_card *card, struct file *file); | 270 | int snd_card_file_remove(struct snd_card *card, struct file *file); |
diff --git a/sound/core/init.c b/sound/core/init.c index 96194599e82e..35419054821c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -181,7 +181,7 @@ void snd_device_initialize(struct device *dev, struct snd_card *card) | |||
181 | EXPORT_SYMBOL_GPL(snd_device_initialize); | 181 | EXPORT_SYMBOL_GPL(snd_device_initialize); |
182 | 182 | ||
183 | static int snd_card_do_free(struct snd_card *card); | 183 | static int snd_card_do_free(struct snd_card *card); |
184 | static const struct attribute_group *card_dev_attr_groups[]; | 184 | static const struct attribute_group card_dev_attr_group; |
185 | 185 | ||
186 | static void release_card_device(struct device *dev) | 186 | static void release_card_device(struct device *dev) |
187 | { | 187 | { |
@@ -269,7 +269,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, | |||
269 | card->card_dev.parent = parent; | 269 | card->card_dev.parent = parent; |
270 | card->card_dev.class = sound_class; | 270 | card->card_dev.class = sound_class; |
271 | card->card_dev.release = release_card_device; | 271 | card->card_dev.release = release_card_device; |
272 | card->card_dev.groups = card_dev_attr_groups; | 272 | card->card_dev.groups = card->dev_groups; |
273 | card->dev_groups[0] = &card_dev_attr_group; | ||
273 | err = kobject_set_name(&card->card_dev.kobj, "card%d", idx); | 274 | err = kobject_set_name(&card->card_dev.kobj, "card%d", idx); |
274 | if (err < 0) | 275 | if (err < 0) |
275 | goto __error; | 276 | goto __error; |
@@ -700,14 +701,32 @@ static struct attribute *card_dev_attrs[] = { | |||
700 | NULL | 701 | NULL |
701 | }; | 702 | }; |
702 | 703 | ||
703 | static struct attribute_group card_dev_attr_group = { | 704 | static const struct attribute_group card_dev_attr_group = { |
704 | .attrs = card_dev_attrs, | 705 | .attrs = card_dev_attrs, |
705 | }; | 706 | }; |
706 | 707 | ||
707 | static const struct attribute_group *card_dev_attr_groups[] = { | 708 | /** |
708 | &card_dev_attr_group, | 709 | * snd_card_add_dev_attr - Append a new sysfs attribute group to card |
709 | NULL | 710 | * @card: card instance |
711 | * @group: attribute group to append | ||
712 | */ | ||
713 | int snd_card_add_dev_attr(struct snd_card *card, | ||
714 | const struct attribute_group *group) | ||
715 | { | ||
716 | int i; | ||
717 | |||
718 | /* loop for (arraysize-1) here to keep NULL at the last entry */ | ||
719 | for (i = 0; i < ARRAY_SIZE(card->dev_groups) - 1; i++) { | ||
720 | if (!card->dev_groups[i]) { | ||
721 | card->dev_groups[i] = group; | ||
722 | return 0; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | dev_err(card->dev, "Too many groups assigned\n"); | ||
727 | return -ENOSPC; | ||
710 | }; | 728 | }; |
729 | EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); | ||
711 | 730 | ||
712 | /** | 731 | /** |
713 | * snd_card_register - register the soundcard | 732 | * snd_card_register - register the soundcard |