diff options
Diffstat (limited to 'sound/core/seq/seq_clientmgr.c')
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 04d4db44fae5..61a07fe34cd2 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -255,12 +255,12 @@ static int seq_free_client1(struct snd_seq_client *client) | |||
255 | 255 | ||
256 | if (!client) | 256 | if (!client) |
257 | return 0; | 257 | return 0; |
258 | snd_seq_delete_all_ports(client); | ||
259 | snd_seq_queue_client_leave(client->number); | ||
260 | spin_lock_irqsave(&clients_lock, flags); | 258 | spin_lock_irqsave(&clients_lock, flags); |
261 | clienttablock[client->number] = 1; | 259 | clienttablock[client->number] = 1; |
262 | clienttab[client->number] = NULL; | 260 | clienttab[client->number] = NULL; |
263 | spin_unlock_irqrestore(&clients_lock, flags); | 261 | spin_unlock_irqrestore(&clients_lock, flags); |
262 | snd_seq_delete_all_ports(client); | ||
263 | snd_seq_queue_client_leave(client->number); | ||
264 | snd_use_lock_sync(&client->use_lock); | 264 | snd_use_lock_sync(&client->use_lock); |
265 | snd_seq_queue_client_termination(client->number); | 265 | snd_seq_queue_client_termination(client->number); |
266 | if (client->pool) | 266 | if (client->pool) |
@@ -910,7 +910,8 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop) | |||
910 | static int snd_seq_client_enqueue_event(struct snd_seq_client *client, | 910 | static int snd_seq_client_enqueue_event(struct snd_seq_client *client, |
911 | struct snd_seq_event *event, | 911 | struct snd_seq_event *event, |
912 | struct file *file, int blocking, | 912 | struct file *file, int blocking, |
913 | int atomic, int hop) | 913 | int atomic, int hop, |
914 | struct mutex *mutexp) | ||
914 | { | 915 | { |
915 | struct snd_seq_event_cell *cell; | 916 | struct snd_seq_event_cell *cell; |
916 | int err; | 917 | int err; |
@@ -948,7 +949,8 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client, | |||
948 | return -ENXIO; /* queue is not allocated */ | 949 | return -ENXIO; /* queue is not allocated */ |
949 | 950 | ||
950 | /* allocate an event cell */ | 951 | /* allocate an event cell */ |
951 | err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic, file); | 952 | err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic, |
953 | file, mutexp); | ||
952 | if (err < 0) | 954 | if (err < 0) |
953 | return err; | 955 | return err; |
954 | 956 | ||
@@ -1017,12 +1019,11 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, | |||
1017 | return -ENXIO; | 1019 | return -ENXIO; |
1018 | 1020 | ||
1019 | /* allocate the pool now if the pool is not allocated yet */ | 1021 | /* allocate the pool now if the pool is not allocated yet */ |
1022 | mutex_lock(&client->ioctl_mutex); | ||
1020 | if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) { | 1023 | if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) { |
1021 | mutex_lock(&client->ioctl_mutex); | ||
1022 | err = snd_seq_pool_init(client->pool); | 1024 | err = snd_seq_pool_init(client->pool); |
1023 | mutex_unlock(&client->ioctl_mutex); | ||
1024 | if (err < 0) | 1025 | if (err < 0) |
1025 | return -ENOMEM; | 1026 | goto out; |
1026 | } | 1027 | } |
1027 | 1028 | ||
1028 | /* only process whole events */ | 1029 | /* only process whole events */ |
@@ -1073,7 +1074,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, | |||
1073 | /* ok, enqueue it */ | 1074 | /* ok, enqueue it */ |
1074 | err = snd_seq_client_enqueue_event(client, &event, file, | 1075 | err = snd_seq_client_enqueue_event(client, &event, file, |
1075 | !(file->f_flags & O_NONBLOCK), | 1076 | !(file->f_flags & O_NONBLOCK), |
1076 | 0, 0); | 1077 | 0, 0, &client->ioctl_mutex); |
1077 | if (err < 0) | 1078 | if (err < 0) |
1078 | break; | 1079 | break; |
1079 | 1080 | ||
@@ -1084,6 +1085,8 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, | |||
1084 | written += len; | 1085 | written += len; |
1085 | } | 1086 | } |
1086 | 1087 | ||
1088 | out: | ||
1089 | mutex_unlock(&client->ioctl_mutex); | ||
1087 | return written ? written : err; | 1090 | return written ? written : err; |
1088 | } | 1091 | } |
1089 | 1092 | ||
@@ -1838,9 +1841,11 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, | |||
1838 | (! snd_seq_write_pool_allocated(client) || | 1841 | (! snd_seq_write_pool_allocated(client) || |
1839 | info->output_pool != client->pool->size)) { | 1842 | info->output_pool != client->pool->size)) { |
1840 | if (snd_seq_write_pool_allocated(client)) { | 1843 | if (snd_seq_write_pool_allocated(client)) { |
1844 | /* is the pool in use? */ | ||
1845 | if (atomic_read(&client->pool->counter)) | ||
1846 | return -EBUSY; | ||
1841 | /* remove all existing cells */ | 1847 | /* remove all existing cells */ |
1842 | snd_seq_pool_mark_closing(client->pool); | 1848 | snd_seq_pool_mark_closing(client->pool); |
1843 | snd_seq_queue_client_leave_cells(client->number); | ||
1844 | snd_seq_pool_done(client->pool); | 1849 | snd_seq_pool_done(client->pool); |
1845 | } | 1850 | } |
1846 | client->pool->size = info->output_pool; | 1851 | client->pool->size = info->output_pool; |
@@ -2260,7 +2265,8 @@ static int kernel_client_enqueue(int client, struct snd_seq_event *ev, | |||
2260 | if (! cptr->accept_output) | 2265 | if (! cptr->accept_output) |
2261 | result = -EPERM; | 2266 | result = -EPERM; |
2262 | else /* send it */ | 2267 | else /* send it */ |
2263 | result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, atomic, hop); | 2268 | result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, |
2269 | atomic, hop, NULL); | ||
2264 | 2270 | ||
2265 | snd_seq_client_unlock(cptr); | 2271 | snd_seq_client_unlock(cptr); |
2266 | return result; | 2272 | return result; |