aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-06-23 08:38:23 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:36:58 -0400
commitc461482c8072bb073e6146db320d3da85cdc89ad (patch)
tree3b69cfd292a488a8cb57ac9b040bd2b1b1a1e26d /sound/core/pcm.c
parent746d4a02e68499fc6c1f8d0c43d2271853ade181 (diff)
[ALSA] Unregister device files at disconnection
Orignally proposed by Sam Revitch <sam.revitch@gmail.com>. Unregister device files at disconnection to avoid the futher accesses. Also, the dev_unregister callback is removed and replaced with the combination of disconnect + free. A new function snd_card_free_when_closed() is introduced, which is used in USB disconnect callback. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r--sound/core/pcm.c48
1 files changed, 18 insertions, 30 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index b8602471f7e5..f52178abf120 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -42,7 +42,6 @@ static int snd_pcm_free(struct snd_pcm *pcm);
42static int snd_pcm_dev_free(struct snd_device *device); 42static int snd_pcm_dev_free(struct snd_device *device);
43static int snd_pcm_dev_register(struct snd_device *device); 43static int snd_pcm_dev_register(struct snd_device *device);
44static int snd_pcm_dev_disconnect(struct snd_device *device); 44static int snd_pcm_dev_disconnect(struct snd_device *device);
45static int snd_pcm_dev_unregister(struct snd_device *device);
46 45
47static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) 46static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
48{ 47{
@@ -680,7 +679,6 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
680 .dev_free = snd_pcm_dev_free, 679 .dev_free = snd_pcm_dev_free,
681 .dev_register = snd_pcm_dev_register, 680 .dev_register = snd_pcm_dev_register,
682 .dev_disconnect = snd_pcm_dev_disconnect, 681 .dev_disconnect = snd_pcm_dev_disconnect,
683 .dev_unregister = snd_pcm_dev_unregister
684 }; 682 };
685 683
686 snd_assert(rpcm != NULL, return -EINVAL); 684 snd_assert(rpcm != NULL, return -EINVAL);
@@ -724,6 +722,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
724 substream = pstr->substream; 722 substream = pstr->substream;
725 while (substream) { 723 while (substream) {
726 substream_next = substream->next; 724 substream_next = substream->next;
725 snd_pcm_timer_done(substream);
727 snd_pcm_substream_proc_done(substream); 726 snd_pcm_substream_proc_done(substream);
728 kfree(substream); 727 kfree(substream);
729 substream = substream_next; 728 substream = substream_next;
@@ -740,7 +739,12 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
740 739
741static int snd_pcm_free(struct snd_pcm *pcm) 740static int snd_pcm_free(struct snd_pcm *pcm)
742{ 741{
742 struct snd_pcm_notify *notify;
743
743 snd_assert(pcm != NULL, return -ENXIO); 744 snd_assert(pcm != NULL, return -ENXIO);
745 list_for_each_entry(notify, &snd_pcm_notify_list, list) {
746 notify->n_unregister(pcm);
747 }
744 if (pcm->private_free) 748 if (pcm->private_free)
745 pcm->private_free(pcm); 749 pcm->private_free(pcm);
746 snd_pcm_lib_preallocate_free_for_all(pcm); 750 snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -955,35 +959,22 @@ static int snd_pcm_dev_register(struct snd_device *device)
955static int snd_pcm_dev_disconnect(struct snd_device *device) 959static int snd_pcm_dev_disconnect(struct snd_device *device)
956{ 960{
957 struct snd_pcm *pcm = device->device_data; 961 struct snd_pcm *pcm = device->device_data;
958 struct list_head *list; 962 struct snd_pcm_notify *notify;
959 struct snd_pcm_substream *substream; 963 struct snd_pcm_substream *substream;
960 int cidx; 964 int cidx, devtype;
961 965
962 mutex_lock(&register_mutex); 966 mutex_lock(&register_mutex);
967 if (list_empty(&pcm->list))
968 goto unlock;
969
963 list_del_init(&pcm->list); 970 list_del_init(&pcm->list);
964 for (cidx = 0; cidx < 2; cidx++) 971 for (cidx = 0; cidx < 2; cidx++)
965 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) 972 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
966 if (substream->runtime) 973 if (substream->runtime)
967 substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; 974 substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
968 list_for_each(list, &snd_pcm_notify_list) { 975 list_for_each_entry(notify, &snd_pcm_notify_list, list) {
969 struct snd_pcm_notify *notify;
970 notify = list_entry(list, struct snd_pcm_notify, list);
971 notify->n_disconnect(pcm); 976 notify->n_disconnect(pcm);
972 } 977 }
973 mutex_unlock(&register_mutex);
974 return 0;
975}
976
977static int snd_pcm_dev_unregister(struct snd_device *device)
978{
979 int cidx, devtype;
980 struct snd_pcm_substream *substream;
981 struct list_head *list;
982 struct snd_pcm *pcm = device->device_data;
983
984 snd_assert(pcm != NULL, return -ENXIO);
985 mutex_lock(&register_mutex);
986 list_del(&pcm->list);
987 for (cidx = 0; cidx < 2; cidx++) { 978 for (cidx = 0; cidx < 2; cidx++) {
988 devtype = -1; 979 devtype = -1;
989 switch (cidx) { 980 switch (cidx) {
@@ -995,23 +986,20 @@ static int snd_pcm_dev_unregister(struct snd_device *device)
995 break; 986 break;
996 } 987 }
997 snd_unregister_device(devtype, pcm->card, pcm->device); 988 snd_unregister_device(devtype, pcm->card, pcm->device);
998 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
999 snd_pcm_timer_done(substream);
1000 }
1001 list_for_each(list, &snd_pcm_notify_list) {
1002 struct snd_pcm_notify *notify;
1003 notify = list_entry(list, struct snd_pcm_notify, list);
1004 notify->n_unregister(pcm);
1005 } 989 }
990 unlock:
1006 mutex_unlock(&register_mutex); 991 mutex_unlock(&register_mutex);
1007 return snd_pcm_free(pcm); 992 return 0;
1008} 993}
1009 994
1010int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) 995int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1011{ 996{
1012 struct list_head *p; 997 struct list_head *p;
1013 998
1014 snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); 999 snd_assert(notify != NULL &&
1000 notify->n_register != NULL &&
1001 notify->n_unregister != NULL &&
1002 notify->n_disconnect, return -EINVAL);
1015 mutex_lock(&register_mutex); 1003 mutex_lock(&register_mutex);
1016 if (nfree) { 1004 if (nfree) {
1017 list_del(&notify->list); 1005 list_del(&notify->list);