mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
ALSA: seq: Use auto-cleanup for client refcounting
The current code manages the refcount of client in a way like: snd_seq_client *client; client = clientptr(id); .... snd_seq_client_unlock(client); Now we introduce an auto-cleanup macro to manage the unlock implicitly, namely, the above will be replaced like: snd_seq_client *client __free(snd_seq_client) = NULL; client = clientptr(id); and we can forget the unref call. A part of the code in snd_seq_deliver_single_event() is factored out to a function, so that the auto-cleanups can be applied cleanly. This also allows us to replace some left mutex lock/unlock with guard(), and also reduce scoped_guard() to the normal guard(), too. Only code refactoring, and no behavior change. Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20250827080520.7544-5-tiwai@suse.de
This commit is contained in:
parent
d7cd16143b
commit
99e1663395
|
|
@ -495,24 +495,21 @@ static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)
|
||||||
*/
|
*/
|
||||||
static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)
|
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);
|
dest = snd_seq_client_use_ptr(event->dest.client);
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (! dest->accept_input)
|
if (! dest->accept_input)
|
||||||
goto __not_avail;
|
return NULL;
|
||||||
if (snd_seq_ev_is_ump(event))
|
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) &&
|
if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&
|
||||||
! test_bit(event->type, dest->event_filter))
|
! test_bit(event->type, dest->event_filter))
|
||||||
goto __not_avail;
|
return NULL;
|
||||||
|
|
||||||
return dest; /* ok - accessible */
|
return no_free_ptr(dest); /* ok - accessible */
|
||||||
__not_avail:
|
|
||||||
snd_seq_client_unlock(dest);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -609,23 +606,14 @@ int __snd_seq_deliver_single_event(struct snd_seq_client *dest,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* deliver a single event; called from snd_seq_deliver_single_event() */
|
||||||
* deliver an event to the specified destination.
|
static int _snd_seq_deliver_single_event(struct snd_seq_client *client,
|
||||||
* if filter is non-zero, client filter bitmap is tested.
|
struct snd_seq_event *event,
|
||||||
*
|
int atomic, int hop)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
struct snd_seq_client *dest = NULL;
|
struct snd_seq_client *dest __free(snd_seq_client) = NULL;
|
||||||
struct snd_seq_client_port *dest_port = NULL;
|
struct snd_seq_client_port *dest_port = NULL;
|
||||||
int result = -ENOENT;
|
int result = -ENOENT;
|
||||||
int direct;
|
|
||||||
|
|
||||||
direct = snd_seq_ev_is_direct(event);
|
|
||||||
|
|
||||||
dest = get_event_dest_client(event);
|
dest = get_event_dest_client(event);
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
|
|
@ -639,7 +627,7 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
||||||
result = -EPERM;
|
result = -EPERM;
|
||||||
goto __skip;
|
goto __skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest_port->timestamping)
|
if (dest_port->timestamping)
|
||||||
update_timestamp_of_queue(event, dest_port->time_queue,
|
update_timestamp_of_queue(event, dest_port->time_queue,
|
||||||
dest_port->time_real);
|
dest_port->time_real);
|
||||||
|
|
@ -670,12 +658,24 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client,
|
||||||
__skip:
|
__skip:
|
||||||
if (dest_port)
|
if (dest_port)
|
||||||
snd_seq_port_unlock(dest_port);
|
snd_seq_port_unlock(dest_port);
|
||||||
if (dest)
|
return result;
|
||||||
snd_seq_client_unlock(dest);
|
}
|
||||||
|
|
||||||
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -817,7 +817,7 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e
|
||||||
*/
|
*/
|
||||||
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
|
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;
|
int result;
|
||||||
|
|
||||||
if (snd_BUG_ON(!cell))
|
if (snd_BUG_ON(!cell))
|
||||||
|
|
@ -879,7 +879,6 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
|
||||||
snd_seq_cell_free(cell);
|
snd_seq_cell_free(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_seq_client_unlock(client);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1171,8 +1170,7 @@ static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)
|
||||||
static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
|
static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_running_info *info = arg;
|
struct snd_seq_running_info *info = arg;
|
||||||
struct snd_seq_client *cptr;
|
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
/* requested client number */
|
/* requested client number */
|
||||||
cptr = client_load_and_use_ptr(info->client);
|
cptr = client_load_and_use_ptr(info->client);
|
||||||
|
|
@ -1180,25 +1178,16 @@ static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
|
||||||
return -ENOENT; /* don't change !!! */
|
return -ENOENT; /* don't change !!! */
|
||||||
|
|
||||||
#ifdef SNDRV_BIG_ENDIAN
|
#ifdef SNDRV_BIG_ENDIAN
|
||||||
if (!info->big_endian) {
|
if (!info->big_endian)
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto __err;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (info->big_endian) {
|
if (info->big_endian)
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto __err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
if (info->cpu_mode > sizeof(long)) {
|
if (info->cpu_mode > sizeof(long))
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto __err;
|
|
||||||
}
|
|
||||||
cptr->convert32 = (info->cpu_mode < sizeof(long));
|
cptr->convert32 = (info->cpu_mode < sizeof(long));
|
||||||
__err:
|
return 0;
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLIENT_INFO ioctl() */
|
/* CLIENT_INFO ioctl() */
|
||||||
|
|
@ -1234,7 +1223,7 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_client_info *client_info = 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 */
|
/* requested client number */
|
||||||
cptr = client_load_and_use_ptr(client_info->client);
|
cptr = client_load_and_use_ptr(client_info->client);
|
||||||
|
|
@ -1242,8 +1231,6 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
|
||||||
return -ENOENT; /* don't change !!! */
|
return -ENOENT; /* don't change !!! */
|
||||||
|
|
||||||
get_client_info(cptr, client_info);
|
get_client_info(cptr, client_info);
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1373,7 +1360,7 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg)
|
||||||
static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
|
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_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;
|
struct snd_seq_client_port *port;
|
||||||
|
|
||||||
cptr = client_load_and_use_ptr(info->addr.client);
|
cptr = client_load_and_use_ptr(info->addr.client);
|
||||||
|
|
@ -1381,16 +1368,12 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
port = snd_seq_port_use_ptr(cptr, info->addr.port);
|
port = snd_seq_port_use_ptr(cptr, info->addr.port);
|
||||||
if (port == NULL) {
|
if (port == NULL)
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
return -ENOENT; /* don't change */
|
return -ENOENT; /* don't change */
|
||||||
}
|
|
||||||
|
|
||||||
/* get port info */
|
/* get port info */
|
||||||
snd_seq_get_port_info(port, info);
|
snd_seq_get_port_info(port, info);
|
||||||
snd_seq_port_unlock(port);
|
snd_seq_port_unlock(port);
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1478,9 +1461,10 @@ int snd_seq_client_notify_subscription(int client, int port,
|
||||||
static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
|
static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_port_subscribe *subs = arg;
|
|
||||||
int result = -EINVAL;
|
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;
|
struct snd_seq_client_port *sport = NULL, *dport = NULL;
|
||||||
|
|
||||||
receiver = client_load_and_use_ptr(subs->dest.client);
|
receiver = client_load_and_use_ptr(subs->dest.client);
|
||||||
|
|
@ -1510,10 +1494,6 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
|
||||||
snd_seq_port_unlock(sport);
|
snd_seq_port_unlock(sport);
|
||||||
if (dport)
|
if (dport)
|
||||||
snd_seq_port_unlock(dport);
|
snd_seq_port_unlock(dport);
|
||||||
if (sender)
|
|
||||||
snd_seq_client_unlock(sender);
|
|
||||||
if (receiver)
|
|
||||||
snd_seq_client_unlock(receiver);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1524,9 +1504,10 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
|
||||||
static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
|
static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_port_subscribe *subs = arg;
|
|
||||||
int result = -ENXIO;
|
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;
|
struct snd_seq_client_port *sport = NULL, *dport = NULL;
|
||||||
|
|
||||||
receiver = snd_seq_client_use_ptr(subs->dest.client);
|
receiver = snd_seq_client_use_ptr(subs->dest.client);
|
||||||
|
|
@ -1555,10 +1536,6 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
|
||||||
snd_seq_port_unlock(sport);
|
snd_seq_port_unlock(sport);
|
||||||
if (dport)
|
if (dport)
|
||||||
snd_seq_port_unlock(dport);
|
snd_seq_port_unlock(dport);
|
||||||
if (sender)
|
|
||||||
snd_seq_client_unlock(sender);
|
|
||||||
if (receiver)
|
|
||||||
snd_seq_client_unlock(receiver);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1849,7 +1826,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_client_pool *info = 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);
|
cptr = client_load_and_use_ptr(info->client);
|
||||||
if (cptr == NULL)
|
if (cptr == NULL)
|
||||||
|
|
@ -1868,7 +1845,6 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
|
||||||
info->input_pool = 0;
|
info->input_pool = 0;
|
||||||
info->input_free = 0;
|
info->input_free = 0;
|
||||||
}
|
}
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1951,7 +1927,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
|
||||||
{
|
{
|
||||||
struct snd_seq_port_subscribe *subs = arg;
|
struct snd_seq_port_subscribe *subs = arg;
|
||||||
int result;
|
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;
|
struct snd_seq_client_port *sport = NULL;
|
||||||
|
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
|
|
@ -1966,8 +1942,6 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
|
||||||
__end:
|
__end:
|
||||||
if (sport)
|
if (sport)
|
||||||
snd_seq_port_unlock(sport);
|
snd_seq_port_unlock(sport);
|
||||||
if (sender)
|
|
||||||
snd_seq_client_unlock(sender);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -1980,7 +1954,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_query_subs *subs = arg;
|
struct snd_seq_query_subs *subs = arg;
|
||||||
int result = -ENXIO;
|
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_client_port *port = NULL;
|
||||||
struct snd_seq_port_subs_info *group;
|
struct snd_seq_port_subs_info *group;
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
|
|
@ -2031,8 +2005,6 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
|
||||||
__end:
|
__end:
|
||||||
if (port)
|
if (port)
|
||||||
snd_seq_port_unlock(port);
|
snd_seq_port_unlock(port);
|
||||||
if (cptr)
|
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -2045,7 +2017,7 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_client_info *info = 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 */
|
/* search for next client */
|
||||||
if (info->client < INT_MAX)
|
if (info->client < INT_MAX)
|
||||||
|
|
@ -2054,16 +2026,12 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
|
||||||
info->client = 0;
|
info->client = 0;
|
||||||
for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
|
for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
|
||||||
cptr = client_load_and_use_ptr(info->client);
|
cptr = client_load_and_use_ptr(info->client);
|
||||||
if (cptr)
|
if (cptr) {
|
||||||
break; /* found */
|
get_client_info(cptr, info);
|
||||||
|
return 0; /* found */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cptr == NULL)
|
return -ENOENT;
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
get_client_info(cptr, info);
|
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2073,7 +2041,7 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_port_info *info = 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;
|
struct snd_seq_client_port *port = NULL;
|
||||||
|
|
||||||
cptr = client_load_and_use_ptr(info->addr.client);
|
cptr = client_load_and_use_ptr(info->addr.client);
|
||||||
|
|
@ -2083,16 +2051,13 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
|
||||||
/* search for next port */
|
/* search for next port */
|
||||||
info->addr.port++;
|
info->addr.port++;
|
||||||
port = snd_seq_port_query_nearest(cptr, info);
|
port = snd_seq_port_query_nearest(cptr, info);
|
||||||
if (port == NULL) {
|
if (port == NULL)
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
|
||||||
|
|
||||||
/* get port info */
|
/* get port info */
|
||||||
info->addr = port->addr;
|
info->addr = port->addr;
|
||||||
snd_seq_get_port_info(port, info);
|
snd_seq_get_port_info(port, info);
|
||||||
snd_seq_port_unlock(port);
|
snd_seq_port_unlock(port);
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -2157,7 +2122,7 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
|
||||||
{
|
{
|
||||||
struct snd_seq_client_ump_info __user *argp =
|
struct snd_seq_client_ump_info __user *argp =
|
||||||
(struct snd_seq_client_ump_info __user *)arg;
|
(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;
|
int client, type, err = 0;
|
||||||
size_t size;
|
size_t size;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
@ -2180,7 +2145,7 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
|
||||||
scoped_guard(mutex, &cptr->ioctl_mutex) {
|
scoped_guard(mutex, &cptr->ioctl_mutex) {
|
||||||
if (!cptr->midi_version) {
|
if (!cptr->midi_version) {
|
||||||
err = -EBADFD;
|
err = -EBADFD;
|
||||||
goto error;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {
|
if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {
|
||||||
|
|
@ -2190,38 +2155,36 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
|
||||||
p = cptr->ump_info[type];
|
p = cptr->ump_info[type];
|
||||||
if (!p) {
|
if (!p) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto error;
|
break;
|
||||||
}
|
}
|
||||||
if (copy_to_user(argp->info, p, size)) {
|
if (copy_to_user(argp->info, p, size)) {
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
goto error;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cptr->type != USER_CLIENT) {
|
if (cptr->type != USER_CLIENT) {
|
||||||
err = -EBADFD;
|
err = -EBADFD;
|
||||||
goto error;
|
break;
|
||||||
}
|
}
|
||||||
if (!cptr->ump_info) {
|
if (!cptr->ump_info) {
|
||||||
cptr->ump_info = kcalloc(NUM_UMP_INFOS,
|
cptr->ump_info = kcalloc(NUM_UMP_INFOS,
|
||||||
sizeof(void *), GFP_KERNEL);
|
sizeof(void *), GFP_KERNEL);
|
||||||
if (!cptr->ump_info) {
|
if (!cptr->ump_info) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto error;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p = memdup_user(argp->info, size);
|
p = memdup_user(argp->info, size);
|
||||||
if (IS_ERR(p)) {
|
if (IS_ERR(p)) {
|
||||||
err = PTR_ERR(p);
|
err = PTR_ERR(p);
|
||||||
goto error;
|
break;
|
||||||
}
|
}
|
||||||
kfree(cptr->ump_info[type]);
|
kfree(cptr->ump_info[type]);
|
||||||
terminate_ump_info_strings(p, type);
|
terminate_ump_info_strings(p, type);
|
||||||
cptr->ump_info[type] = p;
|
cptr->ump_info[type] = p;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
}
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
if (!err && cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO) {
|
if (!err && cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO) {
|
||||||
if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)
|
if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)
|
||||||
snd_seq_system_ump_notify(client, 0,
|
snd_seq_system_ump_notify(client, 0,
|
||||||
|
|
@ -2434,8 +2397,7 @@ EXPORT_SYMBOL(snd_seq_delete_kernel_client);
|
||||||
int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
|
int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
|
||||||
struct file *file, bool blocking)
|
struct file *file, bool blocking)
|
||||||
{
|
{
|
||||||
struct snd_seq_client *cptr;
|
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
|
||||||
int result;
|
|
||||||
|
|
||||||
if (snd_BUG_ON(!ev))
|
if (snd_BUG_ON(!ev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -2458,16 +2420,13 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!cptr->accept_output) {
|
if (!cptr->accept_output) {
|
||||||
result = -EPERM;
|
return -EPERM;
|
||||||
} else { /* send it */
|
} else { /* send it */
|
||||||
guard(mutex)(&cptr->ioctl_mutex);
|
guard(mutex)(&cptr->ioctl_mutex);
|
||||||
result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,
|
return snd_seq_client_enqueue_event(cptr, ev, file, blocking,
|
||||||
false, 0,
|
false, 0,
|
||||||
&cptr->ioctl_mutex);
|
&cptr->ioctl_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
|
EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
|
||||||
|
|
||||||
|
|
@ -2481,8 +2440,7 @@ EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
|
||||||
int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
|
int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
|
||||||
int atomic, int hop)
|
int atomic, int hop)
|
||||||
{
|
{
|
||||||
struct snd_seq_client *cptr;
|
struct snd_seq_client *cptr __free(snd_seq_client) = NULL;
|
||||||
int result;
|
|
||||||
|
|
||||||
if (snd_BUG_ON(!ev))
|
if (snd_BUG_ON(!ev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -2499,12 +2457,9 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!cptr->accept_output)
|
if (!cptr->accept_output)
|
||||||
result = -EPERM;
|
return -EPERM;
|
||||||
else
|
else
|
||||||
result = snd_seq_deliver_event(cptr, ev, atomic, hop);
|
return snd_seq_deliver_event(cptr, ev, atomic, hop);
|
||||||
|
|
||||||
snd_seq_client_unlock(cptr);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
|
EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
|
||||||
|
|
||||||
|
|
@ -2550,17 +2505,13 @@ EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
|
||||||
/* a similar like above but taking locks; used only from OSS sequencer layer */
|
/* 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)
|
int snd_seq_kernel_client_ioctl(int clientid, unsigned int cmd, void *arg)
|
||||||
{
|
{
|
||||||
struct snd_seq_client *client;
|
struct snd_seq_client *client __free(snd_seq_client) = NULL;
|
||||||
int ret;
|
|
||||||
|
|
||||||
client = client_load_and_use_ptr(clientid);
|
client = client_load_and_use_ptr(clientid);
|
||||||
if (!client)
|
if (!client)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
scoped_guard(mutex, &client->ioctl_mutex) {
|
guard(mutex)(&client->ioctl_mutex);
|
||||||
ret = call_seq_client_ctl(client, cmd, arg);
|
return call_seq_client_ctl(client, cmd, arg);
|
||||||
}
|
|
||||||
snd_seq_client_unlock(client);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_ioctl);
|
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_ioctl);
|
||||||
|
|
||||||
|
|
@ -2590,7 +2541,7 @@ EXPORT_SYMBOL_GPL(snd_seq_kernel_client_get);
|
||||||
void snd_seq_kernel_client_put(struct snd_seq_client *cptr)
|
void snd_seq_kernel_client_put(struct snd_seq_client *cptr)
|
||||||
{
|
{
|
||||||
if (cptr)
|
if (cptr)
|
||||||
snd_seq_client_unlock(cptr);
|
snd_seq_client_unref(cptr);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_put);
|
EXPORT_SYMBOL_GPL(snd_seq_kernel_client_put);
|
||||||
|
|
||||||
|
|
@ -2692,7 +2643,6 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
|
||||||
struct snd_info_buffer *buffer)
|
struct snd_info_buffer *buffer)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
struct snd_seq_client *client;
|
|
||||||
|
|
||||||
snd_iprintf(buffer, "Client info\n");
|
snd_iprintf(buffer, "Client info\n");
|
||||||
snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur);
|
snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur);
|
||||||
|
|
@ -2702,15 +2652,15 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
|
||||||
|
|
||||||
/* list the client table */
|
/* list the client table */
|
||||||
for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
|
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);
|
client = client_load_and_use_ptr(c);
|
||||||
if (client == NULL)
|
if (client == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (client->type == NO_CLIENT) {
|
if (client->type == NO_CLIENT)
|
||||||
snd_seq_client_unlock(client);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&client->ioctl_mutex);
|
guard(mutex)(&client->ioctl_mutex);
|
||||||
snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n",
|
snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n",
|
||||||
c, client->name,
|
c, client->name,
|
||||||
client->type == USER_CLIENT ? "User" : "Kernel",
|
client->type == USER_CLIENT ? "User" : "Kernel",
|
||||||
|
|
@ -2728,8 +2678,6 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,
|
||||||
snd_iprintf(buffer, " Input pool :\n");
|
snd_iprintf(buffer, " Input pool :\n");
|
||||||
snd_seq_info_pool(buffer, client->data.user.fifo->pool, " ");
|
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 */
|
#endif /* CONFIG_SND_PROC_FS */
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ static inline void snd_seq_client_unref(struct snd_seq_client *client)
|
||||||
snd_use_lock_free(&client->use_lock);
|
snd_use_lock_free(&client->use_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define snd_seq_client_unlock(c) snd_seq_client_unref(c)
|
DEFINE_FREE(snd_seq_client, struct snd_seq_client *, if (!IS_ERR_OR_NULL(_T)) snd_seq_client_unref(_T))
|
||||||
|
|
||||||
/* dispatch event to client(s) */
|
/* dispatch event to client(s) */
|
||||||
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop);
|
int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop);
|
||||||
|
|
|
||||||
|
|
@ -178,17 +178,10 @@ static int unsubscribe_port(struct snd_seq_client *client,
|
||||||
static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
|
static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
|
||||||
struct snd_seq_client **cp)
|
struct snd_seq_client **cp)
|
||||||
{
|
{
|
||||||
struct snd_seq_client_port *p;
|
|
||||||
*cp = snd_seq_client_use_ptr(addr->client);
|
*cp = snd_seq_client_use_ptr(addr->client);
|
||||||
if (*cp) {
|
if (!*cp)
|
||||||
p = snd_seq_port_use_ptr(*cp, addr->port);
|
return NULL;
|
||||||
if (! p) {
|
return snd_seq_port_use_ptr(*cp, addr->port);
|
||||||
snd_seq_client_unlock(*cp);
|
|
||||||
*cp = NULL;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
||||||
|
|
@ -218,7 +211,7 @@ static void clear_subscriber_list(struct snd_seq_client *client,
|
||||||
|
|
||||||
list_for_each_safe(p, n, &grp->list_head) {
|
list_for_each_safe(p, n, &grp->list_head) {
|
||||||
struct snd_seq_subscribers *subs;
|
struct snd_seq_subscribers *subs;
|
||||||
struct snd_seq_client *c;
|
struct snd_seq_client *c __free(snd_seq_client) = NULL;
|
||||||
struct snd_seq_client_port *aport;
|
struct snd_seq_client_port *aport;
|
||||||
|
|
||||||
subs = get_subscriber(p, is_src);
|
subs = get_subscriber(p, is_src);
|
||||||
|
|
@ -242,7 +235,6 @@ static void clear_subscriber_list(struct snd_seq_client *client,
|
||||||
delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
|
delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
|
||||||
kfree(subs);
|
kfree(subs);
|
||||||
snd_seq_port_unlock(aport);
|
snd_seq_port_unlock(aport);
|
||||||
snd_seq_client_unlock(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user