hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/sound/core/seq/seq_clientmgr.c
....@@ -1,24 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * ALSA sequencer Client Manager
34 * Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl>
45 * Jaroslav Kysela <perex@perex.cz>
56 * Takashi Iwai <tiwai@suse.de>
6
- *
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License
19
- * along with this program; if not, write to the Free Software
20
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
- *
227 */
238
249 #include <linux/init.h>
....@@ -136,13 +121,13 @@
136121 spin_unlock_irqrestore(&clients_lock, flags);
137122 #ifdef CONFIG_MODULES
138123 if (!in_interrupt()) {
139
- static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
140
- static char card_requested[SNDRV_CARDS];
124
+ static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);
125
+ static DECLARE_BITMAP(card_requested, SNDRV_CARDS);
126
+
141127 if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {
142128 int idx;
143129
144
- if (!client_requested[clientid]) {
145
- client_requested[clientid] = 1;
130
+ if (!test_and_set_bit(clientid, client_requested)) {
146131 for (idx = 0; idx < 15; idx++) {
147132 if (seq_client_load[idx] < 0)
148133 break;
....@@ -157,10 +142,8 @@
157142 int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /
158143 SNDRV_SEQ_CLIENTS_PER_CARD;
159144 if (card < snd_ecards_limit) {
160
- if (! card_requested[card]) {
161
- card_requested[card] = 1;
145
+ if (!test_and_set_bit(card, card_requested))
162146 snd_request_card(card);
163
- }
164147 snd_seq_device_load_drivers();
165148 }
166149 }
....@@ -178,6 +161,41 @@
178161 spin_unlock_irqrestore(&clients_lock, flags);
179162 return client;
180163 }
164
+
165
+/* Take refcount and perform ioctl_mutex lock on the given client;
166
+ * used only for OSS sequencer
167
+ * Unlock via snd_seq_client_ioctl_unlock() below
168
+ */
169
+bool snd_seq_client_ioctl_lock(int clientid)
170
+{
171
+ struct snd_seq_client *client;
172
+
173
+ client = snd_seq_client_use_ptr(clientid);
174
+ if (!client)
175
+ return false;
176
+ mutex_lock(&client->ioctl_mutex);
177
+ /* The client isn't unrefed here; see snd_seq_client_ioctl_unlock() */
178
+ return true;
179
+}
180
+EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock);
181
+
182
+/* Unlock and unref the given client; for OSS sequencer use only */
183
+void snd_seq_client_ioctl_unlock(int clientid)
184
+{
185
+ struct snd_seq_client *client;
186
+
187
+ client = snd_seq_client_use_ptr(clientid);
188
+ if (WARN_ON(!client))
189
+ return;
190
+ mutex_unlock(&client->ioctl_mutex);
191
+ /* The doubly unrefs below are intentional; the first one releases the
192
+ * leftover from snd_seq_client_ioctl_lock() above, and the second one
193
+ * is for releasing snd_seq_client_use_ptr() in this function
194
+ */
195
+ snd_seq_client_unlock(client);
196
+ snd_seq_client_unlock(client);
197
+}
198
+EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock);
181199
182200 static void usage_alloc(struct snd_seq_usage *res, int num)
183201 {
....@@ -203,7 +221,6 @@
203221
204222 static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
205223 {
206
- unsigned long flags;
207224 int c;
208225 struct snd_seq_client *client;
209226
....@@ -224,7 +241,7 @@
224241 mutex_init(&client->ioctl_mutex);
225242
226243 /* find free slot in the client table */
227
- spin_lock_irqsave(&clients_lock, flags);
244
+ spin_lock_irq(&clients_lock);
228245 if (client_index < 0) {
229246 for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
230247 c < SNDRV_SEQ_MAX_CLIENTS;
....@@ -232,17 +249,17 @@
232249 if (clienttab[c] || clienttablock[c])
233250 continue;
234251 clienttab[client->number = c] = client;
235
- spin_unlock_irqrestore(&clients_lock, flags);
252
+ spin_unlock_irq(&clients_lock);
236253 return client;
237254 }
238255 } else {
239256 if (clienttab[client_index] == NULL && !clienttablock[client_index]) {
240257 clienttab[client->number = client_index] = client;
241
- spin_unlock_irqrestore(&clients_lock, flags);
258
+ spin_unlock_irq(&clients_lock);
242259 return client;
243260 }
244261 }
245
- spin_unlock_irqrestore(&clients_lock, flags);
262
+ spin_unlock_irq(&clients_lock);
246263 snd_seq_pool_delete(&client->pool);
247264 kfree(client);
248265 return NULL; /* no free slot found or busy, return failure code */
....@@ -251,23 +268,21 @@
251268
252269 static int seq_free_client1(struct snd_seq_client *client)
253270 {
254
- unsigned long flags;
255
-
256271 if (!client)
257272 return 0;
258
- spin_lock_irqsave(&clients_lock, flags);
273
+ spin_lock_irq(&clients_lock);
259274 clienttablock[client->number] = 1;
260275 clienttab[client->number] = NULL;
261
- spin_unlock_irqrestore(&clients_lock, flags);
276
+ spin_unlock_irq(&clients_lock);
262277 snd_seq_delete_all_ports(client);
263278 snd_seq_queue_client_leave(client->number);
264279 snd_use_lock_sync(&client->use_lock);
265280 snd_seq_queue_client_termination(client->number);
266281 if (client->pool)
267282 snd_seq_pool_delete(&client->pool);
268
- spin_lock_irqsave(&clients_lock, flags);
283
+ spin_lock_irq(&clients_lock);
269284 clienttablock[client->number] = 0;
270
- spin_unlock_irqrestore(&clients_lock, flags);
285
+ spin_unlock_irq(&clients_lock);
271286 return 0;
272287 }
273288
....@@ -307,7 +322,7 @@
307322 struct snd_seq_user_client *user;
308323 int err;
309324
310
- err = nonseekable_open(inode, file);
325
+ err = stream_open(inode, file);
311326 if (err < 0)
312327 return err;
313328
....@@ -393,7 +408,7 @@
393408 if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT))
394409 return -ENXIO;
395410
396
- if (!access_ok(VERIFY_WRITE, buf, count))
411
+ if (!access_ok(buf, count))
397412 return -EFAULT;
398413
399414 /* check client structures are in place */
....@@ -2229,12 +2244,13 @@
22292244 }
22302245 EXPORT_SYMBOL(snd_seq_delete_kernel_client);
22312246
2232
-/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
2233
- * and snd_seq_kernel_client_enqueue_blocking
2247
+/*
2248
+ * exported, called by kernel clients to enqueue events (w/o blocking)
2249
+ *
2250
+ * RETURN VALUE: zero if succeed, negative if error
22342251 */
2235
-static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
2236
- struct file *file, int blocking,
2237
- int atomic, int hop)
2252
+int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
2253
+ struct file *file, bool blocking)
22382254 {
22392255 struct snd_seq_client *cptr;
22402256 int result;
....@@ -2257,40 +2273,20 @@
22572273 if (cptr == NULL)
22582274 return -EINVAL;
22592275
2260
- if (! cptr->accept_output)
2276
+ if (!cptr->accept_output) {
22612277 result = -EPERM;
2262
- else /* send it */
2278
+ } else { /* send it */
2279
+ mutex_lock(&cptr->ioctl_mutex);
22632280 result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
2264
- atomic, hop, NULL);
2281
+ false, 0,
2282
+ &cptr->ioctl_mutex);
2283
+ mutex_unlock(&cptr->ioctl_mutex);
2284
+ }
22652285
22662286 snd_seq_client_unlock(cptr);
22672287 return result;
22682288 }
2269
-
2270
-/*
2271
- * exported, called by kernel clients to enqueue events (w/o blocking)
2272
- *
2273
- * RETURN VALUE: zero if succeed, negative if error
2274
- */
2275
-int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
2276
- int atomic, int hop)
2277
-{
2278
- return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
2279
-}
22802289 EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
2281
-
2282
-/*
2283
- * exported, called by kernel clients to enqueue events (with blocking)
2284
- *
2285
- * RETURN VALUE: zero if succeed, negative if error
2286
- */
2287
-int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev,
2288
- struct file *file,
2289
- int atomic, int hop)
2290
-{
2291
- return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
2292
-}
2293
-EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
22942290
22952291 /*
22962292 * exported, called by kernel clients to dispatch events directly to other