summaryrefslogtreecommitdiff
path: root/sound/core/seq/seq_clientmgr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-09 08:26:55 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-09 08:26:55 -0700
commite57ccca1ba33e1d92cc3bbf8b6304a46948844b0 (patch)
treea988a1f7d1d3250f57761dbea365482300a7b3b2 /sound/core/seq/seq_clientmgr.c
parenta2d635decbfa9c1e4ae15cb05b68b2559f7f827c (diff)
parented97c988bdc61ab6fb5d1f5f02a709844557b68f (diff)
Merge tag 'sound-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "The most significant changes at this cycle are the Sound Open Firmware support from Intel for the common DSP framework along with its support for Intel platforms. It's a door opened to a real "free" firmware (in the sense of FOSS), and other parties show interests in it. In addition to SOF, we've got a bunch of updates and fixes as usual. Some highlights are below. ALSA core: - Cleanups and fixes in ALSA timer code to cover some races spotted by syzkaller - Cleanups and fixes in ALSA sequencer code to cover some races, again unsurprisingly, spotted by syzkaller - Optimize the common page allocation helper with alloc_pages_exact() ASoC: - Add SOF core support, as well as Intel SOF platform support - Generic card driver improvements: support for MCLK/sample rate ratio and pin switches - A big set of improvements to TLV320AIC32x4 drivers - New drivers for Freescale audio mixers, several Intel machines, several Mediatek machines, Meson G12A, Spreadtrum compressed audio and DMA devices HD-audio: - A few Realtek codec fixes for reducing pop noises - Quirks for Chromebooks - Workaround for faulty connection report on AMD/Nvidia HDMI Others: - A quirk for Focusrite Scarlett Solo USB-audio - Add support for MOTU 8pre FireWire - 24bit sample format support in aloop - GUS patch format support (finally, over a decade) in native emux synth code" * tag 'sound-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (375 commits) ASoC: SOF: Fix unused variable warnings ALSA: line6: toneport: Fix broken usage of timer for delayed execution ALSA: aica: Fix a long-time build breakage ALSA: hda/realtek - Support low power consumption for ALC256 ASoC: stm32: i2s: update pcm hardware constraints ASoC: codec: hdac_hdmi: no checking monitor in hw_params ASoC: mediatek: mt6358: save PGA for mixer control ASoC: mediatek: mt6358: save output volume for mixer controls ASoC: mediatek: mt6358: initialize setting when ramping volume ASoC: SOF: core: fix undefined nocodec reference ASoC: SOF: xtensa: fix undefined references ASoC: SOF: Propagate sof_get_ctrl_copy_params() error properly ALSA: hdea/realtek - Headset fixup for System76 Gazelle (gaze14) ALSA: hda/intel: add CometLake PCI IDs ALSA: hda/realtek - Support low power consumption for ALC295 ASoC: rockchip: Fix an uninitialized variable compile warning ASoC: SOF: Fix a compile warning with CONFIG_PCI=n ASoC: da7219: Fix a compile warning at CONFIG_COMMON_CLK=n ASoC: sound/soc/sof/: fix kconfig dependency warning ASoC: stm32: spdifrx: change trace level on iec control ...
Diffstat (limited to 'sound/core/seq/seq_clientmgr.c')
-rw-r--r--sound/core/seq/seq_clientmgr.c109
1 files changed, 58 insertions, 51 deletions
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index a11bdc0350fc..b3f593ee752e 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -179,6 +179,41 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
return client;
}
+/* Take refcount and perform ioctl_mutex lock on the given client;
+ * used only for OSS sequencer
+ * Unlock via snd_seq_client_ioctl_unlock() below
+ */
+bool snd_seq_client_ioctl_lock(int clientid)
+{
+ struct snd_seq_client *client;
+
+ client = snd_seq_client_use_ptr(clientid);
+ if (!client)
+ return false;
+ mutex_lock(&client->ioctl_mutex);
+ /* The client isn't unrefed here; see snd_seq_client_ioctl_unlock() */
+ return true;
+}
+EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock);
+
+/* Unlock and unref the given client; for OSS sequencer use only */
+void snd_seq_client_ioctl_unlock(int clientid)
+{
+ struct snd_seq_client *client;
+
+ client = snd_seq_client_use_ptr(clientid);
+ if (WARN_ON(!client))
+ return;
+ mutex_unlock(&client->ioctl_mutex);
+ /* The doubly unrefs below are intentional; the first one releases the
+ * leftover from snd_seq_client_ioctl_lock() above, and the second one
+ * is for releasing snd_seq_client_use_ptr() in this function
+ */
+ snd_seq_client_unlock(client);
+ snd_seq_client_unlock(client);
+}
+EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock);
+
static void usage_alloc(struct snd_seq_usage *res, int num)
{
res->cur += num;
@@ -203,7 +238,6 @@ int __init client_init_data(void)
static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
{
- unsigned long flags;
int c;
struct snd_seq_client *client;
@@ -224,7 +258,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
mutex_init(&client->ioctl_mutex);
/* find free slot in the client table */
- spin_lock_irqsave(&clients_lock, flags);
+ spin_lock_irq(&clients_lock);
if (client_index < 0) {
for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
c < SNDRV_SEQ_MAX_CLIENTS;
@@ -232,17 +266,17 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
if (clienttab[c] || clienttablock[c])
continue;
clienttab[client->number = c] = client;
- spin_unlock_irqrestore(&clients_lock, flags);
+ spin_unlock_irq(&clients_lock);
return client;
}
} else {
if (clienttab[client_index] == NULL && !clienttablock[client_index]) {
clienttab[client->number = client_index] = client;
- spin_unlock_irqrestore(&clients_lock, flags);
+ spin_unlock_irq(&clients_lock);
return client;
}
}
- spin_unlock_irqrestore(&clients_lock, flags);
+ spin_unlock_irq(&clients_lock);
snd_seq_pool_delete(&client->pool);
kfree(client);
return NULL; /* no free slot found or busy, return failure code */
@@ -251,23 +285,21 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
static int seq_free_client1(struct snd_seq_client *client)
{
- unsigned long flags;
-
if (!client)
return 0;
- spin_lock_irqsave(&clients_lock, flags);
+ spin_lock_irq(&clients_lock);
clienttablock[client->number] = 1;
clienttab[client->number] = NULL;
- spin_unlock_irqrestore(&clients_lock, flags);
+ spin_unlock_irq(&clients_lock);
snd_seq_delete_all_ports(client);
snd_seq_queue_client_leave(client->number);
snd_use_lock_sync(&client->use_lock);
snd_seq_queue_client_termination(client->number);
if (client->pool)
snd_seq_pool_delete(&client->pool);
- spin_lock_irqsave(&clients_lock, flags);
+ spin_lock_irq(&clients_lock);
clienttablock[client->number] = 0;
- spin_unlock_irqrestore(&clients_lock, flags);
+ spin_unlock_irq(&clients_lock);
return 0;
}
@@ -1900,20 +1932,14 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
int result;
struct snd_seq_client *sender = NULL;
struct snd_seq_client_port *sport = NULL;
- struct snd_seq_subscribers *p;
result = -EINVAL;
if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
goto __end;
- p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest);
- if (p) {
- result = 0;
- *subs = p->info;
- } else
- result = -ENOENT;
-
+ result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest,
+ subs);
__end:
if (sport)
snd_seq_port_unlock(sport);
@@ -2227,12 +2253,13 @@ int snd_seq_delete_kernel_client(int client)
}
EXPORT_SYMBOL(snd_seq_delete_kernel_client);
-/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
- * and snd_seq_kernel_client_enqueue_blocking
+/*
+ * exported, called by kernel clients to enqueue events (w/o blocking)
+ *
+ * RETURN VALUE: zero if succeed, negative if error
*/
-static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
- struct file *file, int blocking,
- int atomic, int hop)
+int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
+ struct file *file, bool blocking)
{
struct snd_seq_client *cptr;
int result;
@@ -2255,41 +2282,21 @@ static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
if (cptr == NULL)
return -EINVAL;
- if (! cptr->accept_output)
+ if (!cptr->accept_output) {
result = -EPERM;
- else /* send it */
+ } else { /* send it */
+ mutex_lock(&cptr->ioctl_mutex);
result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
- atomic, hop, NULL);
+ false, 0,
+ &cptr->ioctl_mutex);
+ mutex_unlock(&cptr->ioctl_mutex);
+ }
snd_seq_client_unlock(cptr);
return result;
}
-
-/*
- * exported, called by kernel clients to enqueue events (w/o blocking)
- *
- * RETURN VALUE: zero if succeed, negative if error
- */
-int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
- int atomic, int hop)
-{
- return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
-}
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
-/*
- * exported, called by kernel clients to enqueue events (with blocking)
- *
- * RETURN VALUE: zero if succeed, negative if error
- */
-int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev,
- struct file *file,
- int atomic, int hop)
-{
- return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
-}
-EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
-
/*
* exported, called by kernel clients to dispatch events directly to other
* clients, bypassing the queues. Event time-stamp will be updated.