From c560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 22 Apr 2015 18:26:38 +0200 Subject: 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 Signed-off-by: Takashi Iwai --- sound/core/info.c | 79 +++++++++---------------------------------------------- 1 file changed, 13 insertions(+), 66 deletions(-) (limited to 'sound/core/info.c') 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); -- cgit v1.2.3