diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-04-22 18:26:38 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-04-24 17:27:57 +0200 |
commit | c560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee (patch) | |
tree | 433dd8c4dd8c53ef7ebe4411f6dbdae7b1e9b74d /sound/core/info.c | |
parent | 886364f679342a381c9cb4a0b2588fb103bb6a22 (diff) | |
download | linux-c560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee.tar.gz linux-c560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee.tar.bz2 linux-c560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee.zip |
ALSA: core: Remove child proc file elements recursively
This patch changes the way to manage the resource release of proc
files: namely, let snd_info_free_entry() freeing the whole children.
This makes it us possible to drop the snd_device_*() management. Then
snd_card_proc_new() becomes merely a wrapper to
snd_info_create_card_entry().
Together with this change, now you need to call snd_info_free_entry()
for a proc entry created via snd_card_proc_new(), while it was freed
via snd_device_free() beforehand.
Acked-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/info.c')
-rw-r--r-- | sound/core/info.c | 79 |
1 files changed, 13 insertions, 66 deletions
diff --git a/sound/core/info.c b/sound/core/info.c index 9c6db5c24da7..96451a130199 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -760,92 +760,39 @@ EXPORT_SYMBOL(snd_info_create_card_entry); static void snd_info_disconnect(struct snd_info_entry *entry) { - struct list_head *p, *n; + struct snd_info_entry *p, *n; - list_for_each_safe(p, n, &entry->children) { - snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); - } - - if (! entry->p) + if (!entry->p) return; + list_for_each_entry_safe(p, n, &entry->children, list) + snd_info_disconnect(p); list_del_init(&entry->list); proc_remove(entry->p); entry->p = NULL; } -static int snd_info_dev_free_entry(struct snd_device *device) -{ - struct snd_info_entry *entry = device->device_data; - snd_info_free_entry(entry); - return 0; -} - -static int snd_info_dev_register_entry(struct snd_device *device) -{ - struct snd_info_entry *entry = device->device_data; - return snd_info_register(entry); -} - -/** - * snd_card_proc_new - create an info entry for the given card - * @card: the card instance - * @name: the file name - * @entryp: the pointer to store the new info entry - * - * Creates a new info entry and assigns it to the given card. - * Unlike snd_info_create_card_entry(), this function registers the - * info entry as an ALSA device component, so that it can be - * unregistered/released without explicit call. - * Also, you don't have to register this entry via snd_info_register(), - * since this will be registered by snd_card_register() automatically. - * - * The parent is assumed as card->proc_root. - * - * For releasing this entry, use snd_device_free() instead of - * snd_info_free_entry(). - * - * Return: Zero if successful, or a negative error code on failure. - */ -int snd_card_proc_new(struct snd_card *card, const char *name, - struct snd_info_entry **entryp) -{ - static struct snd_device_ops ops = { - .dev_free = snd_info_dev_free_entry, - .dev_register = snd_info_dev_register_entry, - /* disconnect is done via snd_info_card_disconnect() */ - }; - struct snd_info_entry *entry; - int err; - - entry = snd_info_create_card_entry(card, name, card->proc_root); - if (! entry) - return -ENOMEM; - if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) { - snd_info_free_entry(entry); - return err; - } - if (entryp) - *entryp = entry; - return 0; -} - -EXPORT_SYMBOL(snd_card_proc_new); - /** * snd_info_free_entry - release the info entry * @entry: the info entry * - * Releases the info entry. Don't call this after registered. + * Releases the info entry. */ void snd_info_free_entry(struct snd_info_entry * entry) { - if (entry == NULL) + struct snd_info_entry *p, *n; + + if (!entry) return; if (entry->p) { mutex_lock(&info_mutex); snd_info_disconnect(entry); mutex_unlock(&info_mutex); } + + /* free all children at first */ + list_for_each_entry_safe(p, n, &entry->children, list) + snd_info_free_entry(p); + kfree(entry->name); if (entry->private_free) entry->private_free(entry); |