aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/info.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-06-23 08:37:59 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:36:48 -0400
commit746d4a02e68499fc6c1f8d0c43d2271853ade181 (patch)
treec4a1e9a0e8f5f95a44a3349d9b86490fe837428f /sound/core/info.c
parent42750b04c5baa7c5ffdf0a8be2b9b320efdf069f (diff)
[ALSA] Fix disconnection of proc interface
- Add the linked list to each proc entry to enable a single-shot disconnection (unregister) - Deprecate snd_info_unregister(), use snd_info_free_entry() - Removed NULL checks of snd_info_free_entry() Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/core/info.c')
-rw-r--r--sound/core/info.c102
1 files changed, 50 insertions, 52 deletions
diff --git a/sound/core/info.c b/sound/core/info.c
index 340332c6d973..9663b6be9c3a 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -78,6 +78,7 @@ struct snd_info_private_data {
78 78
79static int snd_info_version_init(void); 79static int snd_info_version_init(void);
80static int snd_info_version_done(void); 80static int snd_info_version_done(void);
81static void snd_info_disconnect(struct snd_info_entry *entry);
81 82
82 83
83/* resize the proc r/w buffer */ 84/* resize the proc r/w buffer */
@@ -304,7 +305,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
304 mutex_lock(&info_mutex); 305 mutex_lock(&info_mutex);
305 p = PDE(inode); 306 p = PDE(inode);
306 entry = p == NULL ? NULL : (struct snd_info_entry *)p->data; 307 entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
307 if (entry == NULL || entry->disconnected) { 308 if (entry == NULL || ! entry->p) {
308 mutex_unlock(&info_mutex); 309 mutex_unlock(&info_mutex);
309 return -ENODEV; 310 return -ENODEV;
310 } 311 }
@@ -586,10 +587,10 @@ int __exit snd_info_done(void)
586 snd_info_version_done(); 587 snd_info_version_done();
587 if (snd_proc_root) { 588 if (snd_proc_root) {
588#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) 589#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
589 snd_info_unregister(snd_seq_root); 590 snd_info_free_entry(snd_seq_root);
590#endif 591#endif
591#ifdef CONFIG_SND_OSSEMUL 592#ifdef CONFIG_SND_OSSEMUL
592 snd_info_unregister(snd_oss_root); 593 snd_info_free_entry(snd_oss_root);
593#endif 594#endif
594 snd_remove_proc_entry(&proc_root, snd_proc_root); 595 snd_remove_proc_entry(&proc_root, snd_proc_root);
595 } 596 }
@@ -648,17 +649,28 @@ int snd_info_card_register(struct snd_card *card)
648 * de-register the card proc file 649 * de-register the card proc file
649 * called from init.c 650 * called from init.c
650 */ 651 */
651int snd_info_card_free(struct snd_card *card) 652void snd_info_card_disconnect(struct snd_card *card)
652{ 653{
653 snd_assert(card != NULL, return -ENXIO); 654 snd_assert(card != NULL, return);
655 mutex_lock(&info_mutex);
654 if (card->proc_root_link) { 656 if (card->proc_root_link) {
655 snd_remove_proc_entry(snd_proc_root, card->proc_root_link); 657 snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
656 card->proc_root_link = NULL; 658 card->proc_root_link = NULL;
657 } 659 }
658 if (card->proc_root) { 660 if (card->proc_root)
659 snd_info_unregister(card->proc_root); 661 snd_info_disconnect(card->proc_root);
660 card->proc_root = NULL; 662 mutex_unlock(&info_mutex);
661 } 663}
664
665/*
666 * release the card proc file resources
667 * called from init.c
668 */
669int snd_info_card_free(struct snd_card *card)
670{
671 snd_assert(card != NULL, return -ENXIO);
672 snd_info_free_entry(card->proc_root);
673 card->proc_root = NULL;
662 return 0; 674 return 0;
663} 675}
664 676
@@ -767,6 +779,8 @@ static struct snd_info_entry *snd_info_create_entry(const char *name)
767 entry->mode = S_IFREG | S_IRUGO; 779 entry->mode = S_IFREG | S_IRUGO;
768 entry->content = SNDRV_INFO_CONTENT_TEXT; 780 entry->content = SNDRV_INFO_CONTENT_TEXT;
769 mutex_init(&entry->access); 781 mutex_init(&entry->access);
782 INIT_LIST_HEAD(&entry->children);
783 INIT_LIST_HEAD(&entry->list);
770 return entry; 784 return entry;
771} 785}
772 786
@@ -819,30 +833,35 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
819 833
820EXPORT_SYMBOL(snd_info_create_card_entry); 834EXPORT_SYMBOL(snd_info_create_card_entry);
821 835
822static int snd_info_dev_free_entry(struct snd_device *device) 836static void snd_info_disconnect(struct snd_info_entry *entry)
823{ 837{
824 struct snd_info_entry *entry = device->device_data; 838 struct list_head *p, *n;
825 snd_info_free_entry(entry); 839 struct proc_dir_entry *root;
826 return 0;
827}
828 840
829static int snd_info_dev_register_entry(struct snd_device *device) 841 list_for_each_safe(p, n, &entry->children) {
830{ 842 snd_info_disconnect(list_entry(p, struct snd_info_entry, list));
831 struct snd_info_entry *entry = device->device_data; 843 }
832 return snd_info_register(entry); 844
845 if (! entry->p)
846 return;
847 list_del_init(&entry->list);
848 root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
849 snd_assert(root, return);
850 snd_remove_proc_entry(root, entry->p);
851 entry->p = NULL;
833} 852}
834 853
835static int snd_info_dev_disconnect_entry(struct snd_device *device) 854static int snd_info_dev_free_entry(struct snd_device *device)
836{ 855{
837 struct snd_info_entry *entry = device->device_data; 856 struct snd_info_entry *entry = device->device_data;
838 entry->disconnected = 1; 857 snd_info_free_entry(entry);
839 return 0; 858 return 0;
840} 859}
841 860
842static int snd_info_dev_unregister_entry(struct snd_device *device) 861static int snd_info_dev_register_entry(struct snd_device *device)
843{ 862{
844 struct snd_info_entry *entry = device->device_data; 863 struct snd_info_entry *entry = device->device_data;
845 return snd_info_unregister(entry); 864 return snd_info_register(entry);
846} 865}
847 866
848/** 867/**
@@ -871,8 +890,7 @@ int snd_card_proc_new(struct snd_card *card, const char *name,
871 static struct snd_device_ops ops = { 890 static struct snd_device_ops ops = {
872 .dev_free = snd_info_dev_free_entry, 891 .dev_free = snd_info_dev_free_entry,
873 .dev_register = snd_info_dev_register_entry, 892 .dev_register = snd_info_dev_register_entry,
874 .dev_disconnect = snd_info_dev_disconnect_entry, 893 /* disconnect is done via snd_info_card_disconnect() */
875 .dev_unregister = snd_info_dev_unregister_entry
876 }; 894 };
877 struct snd_info_entry *entry; 895 struct snd_info_entry *entry;
878 int err; 896 int err;
@@ -901,6 +919,11 @@ void snd_info_free_entry(struct snd_info_entry * entry)
901{ 919{
902 if (entry == NULL) 920 if (entry == NULL)
903 return; 921 return;
922 if (entry->p) {
923 mutex_lock(&info_mutex);
924 snd_info_disconnect(entry);
925 mutex_unlock(&info_mutex);
926 }
904 kfree(entry->name); 927 kfree(entry->name);
905 if (entry->private_free) 928 if (entry->private_free)
906 entry->private_free(entry); 929 entry->private_free(entry);
@@ -935,38 +958,14 @@ int snd_info_register(struct snd_info_entry * entry)
935 p->size = entry->size; 958 p->size = entry->size;
936 p->data = entry; 959 p->data = entry;
937 entry->p = p; 960 entry->p = p;
961 if (entry->parent)
962 list_add_tail(&entry->list, &entry->parent->children);
938 mutex_unlock(&info_mutex); 963 mutex_unlock(&info_mutex);
939 return 0; 964 return 0;
940} 965}
941 966
942EXPORT_SYMBOL(snd_info_register); 967EXPORT_SYMBOL(snd_info_register);
943 968
944/**
945 * snd_info_unregister - de-register the info entry
946 * @entry: the info entry
947 *
948 * De-registers the info entry and releases the instance.
949 *
950 * Returns zero if successful, or a negative error code on failure.
951 */
952int snd_info_unregister(struct snd_info_entry * entry)
953{
954 struct proc_dir_entry *root;
955
956 if (! entry)
957 return 0;
958 snd_assert(entry->p != NULL, return -ENXIO);
959 root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
960 snd_assert(root, return -ENXIO);
961 mutex_lock(&info_mutex);
962 snd_remove_proc_entry(root, entry->p);
963 mutex_unlock(&info_mutex);
964 snd_info_free_entry(entry);
965 return 0;
966}
967
968EXPORT_SYMBOL(snd_info_unregister);
969
970/* 969/*
971 970
972 */ 971 */
@@ -999,8 +998,7 @@ static int __init snd_info_version_init(void)
999 998
1000static int __exit snd_info_version_done(void) 999static int __exit snd_info_version_done(void)
1001{ 1000{
1002 if (snd_info_version_entry) 1001 snd_info_free_entry(snd_info_version_entry);
1003 snd_info_unregister(snd_info_version_entry);
1004 return 0; 1002 return 0;
1005} 1003}
1006 1004