aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/info.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-04-22 12:26:38 -0400
committerTakashi Iwai <tiwai@suse.de>2015-04-24 11:27:57 -0400
commitc560a6797e3bec1e04f1f6f9f3c2135db0f5c8ee (patch)
tree433dd8c4dd8c53ef7ebe4411f6dbdae7b1e9b74d /sound/core/info.c
parent886364f679342a381c9cb4a0b2588fb103bb6a22 (diff)
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.c79
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);
760 760
761static void snd_info_disconnect(struct snd_info_entry *entry) 761static void snd_info_disconnect(struct snd_info_entry *entry)
762{ 762{
763 struct list_head *p, *n; 763 struct snd_info_entry *p, *n;
764 764
765 list_for_each_safe(p, n, &entry->children) { 765 if (!entry->p)
766 snd_info_disconnect(list_entry(p, struct snd_info_entry, list));
767 }
768
769 if (! entry->p)
770 return; 766 return;
767 list_for_each_entry_safe(p, n, &entry->children, list)
768 snd_info_disconnect(p);
771 list_del_init(&entry->list); 769 list_del_init(&entry->list);
772 proc_remove(entry->p); 770 proc_remove(entry->p);
773 entry->p = NULL; 771 entry->p = NULL;
774} 772}
775 773
776static int snd_info_dev_free_entry(struct snd_device *device)
777{
778 struct snd_info_entry *entry = device->device_data;
779 snd_info_free_entry(entry);
780 return 0;
781}
782
783static int snd_info_dev_register_entry(struct snd_device *device)
784{
785 struct snd_info_entry *entry = device->device_data;
786 return snd_info_register(entry);
787}
788
789/**
790 * snd_card_proc_new - create an info entry for the given card
791 * @card: the card instance
792 * @name: the file name
793 * @entryp: the pointer to store the new info entry
794 *
795 * Creates a new info entry and assigns it to the given card.
796 * Unlike snd_info_create_card_entry(), this function registers the
797 * info entry as an ALSA device component, so that it can be
798 * unregistered/released without explicit call.
799 * Also, you don't have to register this entry via snd_info_register(),
800 * since this will be registered by snd_card_register() automatically.
801 *
802 * The parent is assumed as card->proc_root.
803 *
804 * For releasing this entry, use snd_device_free() instead of
805 * snd_info_free_entry().
806 *
807 * Return: Zero if successful, or a negative error code on failure.
808 */
809int snd_card_proc_new(struct snd_card *card, const char *name,
810 struct snd_info_entry **entryp)
811{
812 static struct snd_device_ops ops = {
813 .dev_free = snd_info_dev_free_entry,
814 .dev_register = snd_info_dev_register_entry,
815 /* disconnect is done via snd_info_card_disconnect() */
816 };
817 struct snd_info_entry *entry;
818 int err;
819
820 entry = snd_info_create_card_entry(card, name, card->proc_root);
821 if (! entry)
822 return -ENOMEM;
823 if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) {
824 snd_info_free_entry(entry);
825 return err;
826 }
827 if (entryp)
828 *entryp = entry;
829 return 0;
830}
831
832EXPORT_SYMBOL(snd_card_proc_new);
833
834/** 774/**
835 * snd_info_free_entry - release the info entry 775 * snd_info_free_entry - release the info entry
836 * @entry: the info entry 776 * @entry: the info entry
837 * 777 *
838 * Releases the info entry. Don't call this after registered. 778 * Releases the info entry.
839 */ 779 */
840void snd_info_free_entry(struct snd_info_entry * entry) 780void snd_info_free_entry(struct snd_info_entry * entry)
841{ 781{
842 if (entry == NULL) 782 struct snd_info_entry *p, *n;
783
784 if (!entry)
843 return; 785 return;
844 if (entry->p) { 786 if (entry->p) {
845 mutex_lock(&info_mutex); 787 mutex_lock(&info_mutex);
846 snd_info_disconnect(entry); 788 snd_info_disconnect(entry);
847 mutex_unlock(&info_mutex); 789 mutex_unlock(&info_mutex);
848 } 790 }
791
792 /* free all children at first */
793 list_for_each_entry_safe(p, n, &entry->children, list)
794 snd_info_free_entry(p);
795
849 kfree(entry->name); 796 kfree(entry->name);
850 if (entry->private_free) 797 if (entry->private_free)
851 entry->private_free(entry); 798 entry->private_free(entry);