*/
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
{
- struct snd_seq_client *dest;
+ struct snd_seq_client *dest __free(snd_seq_client) = NULL;
dest = snd_seq_client_use_ptr(event->dest.client);
if (dest == NULL)
return NULL;
if (! dest->accept_input)
- goto __not_avail;
+ return NULL;
if (snd_seq_ev_is_ump(event))
- return dest; /* ok - no filter checks */
+ return no_free_ptr(dest); /* ok - no filter checks */
if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
! test_bit(event->type, dest->event_filter))
- goto __not_avail;
+ return NULL;
- return dest; /* ok - accessible */
-__not_avail:
- snd_seq_client_unlock(dest);
- return NULL;
+ return no_free_ptr(dest); /* ok - accessible */
}
return 0;
}
-/*
- * deliver an event to the specified destination.
- * if filter is non-zero, client filter bitmap is tested.
- *
- * RETURN VALUE: 0 : if succeeded
- * <0 : error
- */
-static int snd_seq_deliver_single_event(struct snd_seq_client *client,
- struct snd_seq_event *event,
- int atomic, int hop)
+/* deliver a single event; called from snd_seq_deliver_single_event() */
+static int _snd_seq_deliver_single_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
+ int atomic, int hop)
{
- struct snd_seq_client *dest = NULL;
+ struct snd_seq_client *dest __free(snd_seq_client) = NULL;
struct snd_seq_client_port *dest_port = NULL;
int result = -ENOENT;
- int direct;
-
- direct = snd_seq_ev_is_direct(event);
dest = get_event_dest_client(event);
if (dest == NULL)
result = -EPERM;
goto __skip;
}
-
+
if (dest_port->timestamping)
update_timestamp_of_queue(event, dest_port->time_queue,
dest_port->time_real);
__skip:
if (dest_port)
snd_seq_port_unlock(dest_port);
- if (dest)
- snd_seq_client_unlock(dest);
+ return result;
+}
- if (result < 0 && !direct) {
- result = bounce_error_event(client, event, result, atomic, hop);
- }
+/*
+ * deliver an event to the specified destination.
+ * if filter is non-zero, client filter bitmap is tested.
+ *
+ * RETURN VALUE: 0 : if succeeded
+ * <0 : error
+ */
+static int snd_seq_deliver_single_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
+ int atomic, int hop)
+{
+ int result = _snd_seq_deliver_single_event(client, event, atomic, hop);
+
+ if (result < 0 && !snd_seq_ev_is_direct(event))
+ return bounce_error_event(client, event, result, atomic, hop);
return result;
}
*/
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
- struct snd_seq_client *client;
+ struct snd_seq_client *client __free(snd_seq_client) = NULL;
int result;
if (snd_BUG_ON(!cell))
snd_seq_cell_free(cell);
}
- snd_seq_client_unlock(client);
return result;
}
static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
{
struct snd_seq_running_info *info = arg;
- struct snd_seq_client *cptr;
- int err = 0;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
/* requested client number */
cptr = client_load_and_use_ptr(info->client);
return -ENOENT; /* don't change !!! */
#ifdef SNDRV_BIG_ENDIAN
- if (!info->big_endian) {
- err = -EINVAL;
- goto __err;
- }
+ if (!info->big_endian)
+ return -EINVAL;
#else
- if (info->big_endian) {
- err = -EINVAL;
- goto __err;
- }
-
+ if (info->big_endian)
+ return -EINVAL;
#endif
- if (info->cpu_mode > sizeof(long)) {
- err = -EINVAL;
- goto __err;
- }
+ if (info->cpu_mode > sizeof(long))
+ return -EINVAL;
cptr->convert32 = (info->cpu_mode < sizeof(long));
- __err:
- snd_seq_client_unlock(cptr);
- return err;
+ return 0;
}
/* CLIENT_INFO ioctl() */
void *arg)
{
struct snd_seq_client_info *client_info = arg;
- struct snd_seq_client *cptr;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
/* requested client number */
cptr = client_load_and_use_ptr(client_info->client);
return -ENOENT; /* don't change !!! */
get_client_info(cptr, client_info);
- snd_seq_client_unlock(cptr);
-
return 0;
}
static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
{
struct snd_seq_port_info *info = arg;
- struct snd_seq_client *cptr;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client_port *port;
cptr = client_load_and_use_ptr(info->addr.client);
return -ENXIO;
port = snd_seq_port_use_ptr(cptr, info->addr.port);
- if (port == NULL) {
- snd_seq_client_unlock(cptr);
+ if (port == NULL)
return -ENOENT; /* don't change */
- }
/* get port info */
snd_seq_get_port_info(port, info);
snd_seq_port_unlock(port);
- snd_seq_client_unlock(cptr);
-
return 0;
}
static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
void *arg)
{
- struct snd_seq_port_subscribe *subs = arg;
int result = -EINVAL;
- struct snd_seq_client *receiver = NULL, *sender = NULL;
+ struct snd_seq_port_subscribe *subs = arg;
+ struct snd_seq_client *receiver __free(snd_seq_client) = NULL;
+ struct snd_seq_client *sender __free(snd_seq_client) = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL;
receiver = client_load_and_use_ptr(subs->dest.client);
snd_seq_port_unlock(sport);
if (dport)
snd_seq_port_unlock(dport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (receiver)
- snd_seq_client_unlock(receiver);
return result;
}
static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
void *arg)
{
- struct snd_seq_port_subscribe *subs = arg;
int result = -ENXIO;
- struct snd_seq_client *receiver = NULL, *sender = NULL;
+ struct snd_seq_port_subscribe *subs = arg;
+ struct snd_seq_client *receiver __free(snd_seq_client) = NULL;
+ struct snd_seq_client *sender __free(snd_seq_client) = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL;
receiver = snd_seq_client_use_ptr(subs->dest.client);
snd_seq_port_unlock(sport);
if (dport)
snd_seq_port_unlock(dport);
- if (sender)
- snd_seq_client_unlock(sender);
- if (receiver)
- snd_seq_client_unlock(receiver);
return result;
}
void *arg)
{
struct snd_seq_client_pool *info = arg;
- struct snd_seq_client *cptr;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
cptr = client_load_and_use_ptr(info->client);
if (cptr == NULL)
info->input_pool = 0;
info->input_free = 0;
}
- snd_seq_client_unlock(cptr);
return 0;
}
{
struct snd_seq_port_subscribe *subs = arg;
int result;
- struct snd_seq_client *sender = NULL;
+ struct snd_seq_client *sender __free(snd_seq_client) = NULL;
struct snd_seq_client_port *sport = NULL;
result = -EINVAL;
__end:
if (sport)
snd_seq_port_unlock(sport);
- if (sender)
- snd_seq_client_unlock(sender);
return result;
}
{
struct snd_seq_query_subs *subs = arg;
int result = -ENXIO;
- struct snd_seq_client *cptr = NULL;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client_port *port = NULL;
struct snd_seq_port_subs_info *group;
struct list_head *p;
__end:
if (port)
snd_seq_port_unlock(port);
- if (cptr)
- snd_seq_client_unlock(cptr);
return result;
}
void *arg)
{
struct snd_seq_client_info *info = arg;
- struct snd_seq_client *cptr = NULL;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
/* search for next client */
if (info->client < INT_MAX)
info->client = 0;
for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
cptr = client_load_and_use_ptr(info->client);
- if (cptr)
- break; /* found */
+ if (cptr) {
+ get_client_info(cptr, info);
+ return 0; /* found */
+ }
}
- if (cptr == NULL)
- return -ENOENT;
-
- get_client_info(cptr, info);
- snd_seq_client_unlock(cptr);
-
- return 0;
+ return -ENOENT;
}
/*
void *arg)
{
struct snd_seq_port_info *info = arg;
- struct snd_seq_client *cptr;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
struct snd_seq_client_port *port = NULL;
cptr = client_load_and_use_ptr(info->addr.client);
/* search for next port */
info->addr.port++;
port = snd_seq_port_query_nearest(cptr, info);
- if (port == NULL) {
- snd_seq_client_unlock(cptr);
+ if (port == NULL)
return -ENOENT;
- }
/* get port info */
info->addr = port->addr;
snd_seq_get_port_info(port, info);
snd_seq_port_unlock(port);
- snd_seq_client_unlock(cptr);
return 0;
}
{
struct snd_seq_client_ump_info __user *argp =
(struct snd_seq_client_ump_info __user *)arg;
- struct snd_seq_client *cptr;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
int client, type, err = 0;
size_t size;
void *p;
scoped_guard(mutex, &cptr->ioctl_mutex) {
if (!cptr->midi_version) {
err = -EBADFD;
- goto error;
+ break;
}
if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {
p = cptr->ump_info[type];
if (!p) {
err = -ENODEV;
- goto error;
+ break;
}
if (copy_to_user(argp->info, p, size)) {
err = -EFAULT;
- goto error;
+ break;
}
} else {
if (cptr->type != USER_CLIENT) {
err = -EBADFD;
- goto error;
+ break;
}
if (!cptr->ump_info) {
cptr->ump_info = kcalloc(NUM_UMP_INFOS,
sizeof(void *), GFP_KERNEL);
if (!cptr->ump_info) {
err = -ENOMEM;
- goto error;
+ break;
}
}
p = memdup_user(argp->info, size);
if (IS_ERR(p)) {
err = PTR_ERR(p);
- goto error;
+ break;
}
kfree(cptr->ump_info[type]);
terminate_ump_info_strings(p, type);
cptr->ump_info[type] = p;
}
- }
- error:
- snd_seq_client_unlock(cptr);
+ }
if (!err && cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO) {
if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)
snd_seq_system_ump_notify(client, 0,
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;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
if (snd_BUG_ON(!ev))
return -EINVAL;
return -EINVAL;
if (!cptr->accept_output) {
- result = -EPERM;
+ return -EPERM;
} else { /* send it */
guard(mutex)(&cptr->ioctl_mutex);
- result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
- false, 0,
- &cptr->ioctl_mutex);
+ return snd_seq_client_enqueue_event(cptr, ev, file, blocking,
+ false, 0,
+ &cptr->ioctl_mutex);
}
-
- snd_seq_client_unlock(cptr);
- return result;
}
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
int atomic, int hop)
{
- struct snd_seq_client *cptr;
- int result;
+ struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
if (snd_BUG_ON(!ev))
return -EINVAL;
return -EINVAL;
if (!cptr->accept_output)
- result = -EPERM;
+ return -EPERM;
else
- result = snd_seq_deliver_event(cptr, ev, atomic, hop);
-
- snd_seq_client_unlock(cptr);
- return result;
+ return snd_seq_deliver_event(cptr, ev, atomic, hop);
}
EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
/* a similar like above but taking locks; used only from OSS sequencer layer */
int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg)
{
- struct snd_seq_client *client;
- int ret;
+ struct snd_seq_client *client __free(snd_seq_client) = NULL;
client = client_load_and_use_ptr(clientid);
if (!client)
return -ENXIO;
- scoped_guard(mutex, &client->ioctl_mutex) {
- ret = call_seq_client_ctl(client, cmd, arg);
- }
- snd_seq_client_unlock(client);
- return ret;
+ guard(mutex)(&client->ioctl_mutex);
+ return call_seq_client_ctl(client, cmd, arg);
}
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_ioctl);
void snd_seq_kernel_client_put(struct snd_seq_client *cptr)
{
if (cptr)
- snd_seq_client_unlock(cptr);
+ snd_seq_client_unref(cptr);
}
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_put);
struct snd_info_buffer *buffer)
{
int c;
- struct snd_seq_client *client;
snd_iprintf(buffer, "Client info\n");
snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur);
/* list the client table */
for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
+ struct snd_seq_client *client __free(snd_seq_client) = NULL;
+
client = client_load_and_use_ptr(c);
if (client == NULL)
continue;
- if (client->type == NO_CLIENT) {
- snd_seq_client_unlock(client);
+ if (client->type == NO_CLIENT)
continue;
- }
- mutex_lock(&client->ioctl_mutex);
+ guard(mutex)(&client->ioctl_mutex);
snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n",
c, client->name,
client->type == USER_CLIENT ? "User" : "Kernel",
snd_iprintf(buffer, " Input pool :\n");
snd_seq_info_pool(buffer, client->data.user.fifo->pool, " ");
}
- mutex_unlock(&client->ioctl_mutex);
- snd_seq_client_unlock(client);
}
}
#endif /* CONFIG_SND_PROC_FS */