diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-06-23 08:37:59 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:36:48 -0400 |
commit | 746d4a02e68499fc6c1f8d0c43d2271853ade181 (patch) | |
tree | c4a1e9a0e8f5f95a44a3349d9b86490fe837428f /sound/core/info.c | |
parent | 42750b04c5baa7c5ffdf0a8be2b9b320efdf069f (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.c | 102 |
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 | ||
79 | static int snd_info_version_init(void); | 79 | static int snd_info_version_init(void); |
80 | static int snd_info_version_done(void); | 80 | static int snd_info_version_done(void); |
81 | static 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 | */ |
651 | int snd_info_card_free(struct snd_card *card) | 652 | void 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 | */ | ||
669 | int 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 | ||
820 | EXPORT_SYMBOL(snd_info_create_card_entry); | 834 | EXPORT_SYMBOL(snd_info_create_card_entry); |
821 | 835 | ||
822 | static int snd_info_dev_free_entry(struct snd_device *device) | 836 | static 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 | ||
829 | static 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 | ||
835 | static int snd_info_dev_disconnect_entry(struct snd_device *device) | 854 | static 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 | ||
842 | static int snd_info_dev_unregister_entry(struct snd_device *device) | 861 | static 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 | ||
942 | EXPORT_SYMBOL(snd_info_register); | 967 | EXPORT_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 | */ | ||
952 | int 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 | |||
968 | EXPORT_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 | ||
1000 | static int __exit snd_info_version_done(void) | 999 | static 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 | ||