]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ALSA: seq: Register kernel port with full information
authorTakashi Iwai <tiwai@suse.de>
Tue, 19 May 2026 09:42:52 +0000 (11:42 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 20 May 2026 05:47:33 +0000 (07:47 +0200)
The current ALSA sequencer core tries to register the new kernel
sequencer port on the list at first, then fill up the port
information.  This means that user-space may sneak the wrong
information before the actual data is filled, which isn't ideal.
Although the user-space should try to query the port info after the
port registration notification is sent out, it'd be still better to
have a port available with the full info from the beginning.

This patch changes the sequencer port creation and registration
procedure; now split to two steps, for creation and insertion, and the
port is registered after the information is filled.

Link: https://sashiko.dev/#/patchset/20260518194023.1667857-1-maoyixie.tju%40gmail.com
Link: https://patch.msgid.link/20260519094254.465041-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_ports.c
sound/core/seq/seq_ports.h

index 5719637575a9113df0aca09544654c301a79115f..19d6fea012f6ae37d5bc4c0565bf49b989464542 100644 (file)
@@ -1287,7 +1287,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
                port_idx = -1;
        if (port_idx >= SNDRV_SEQ_ADDRESS_UNKNOWN)
                return -EINVAL;
-       err = snd_seq_create_port(client, port_idx, &port);
+       err = snd_seq_create_port(client, &port);
        if (err < 0)
                return err;
 
@@ -1309,6 +1309,11 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
        info->addr = port->addr;
 
        snd_seq_set_port_info(port, info);
+       err = snd_seq_insert_port(client, port_idx, port);
+       if (err < 0) {
+               kfree(port);
+               return err;
+       }
        if (info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT)
                client->ump_endpoint_port = port->addr.port;
        snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
index 31ab4681c60124f4cfc11ad0d318489ad30e29a7..17daacd4476aaa7e5bf368a3e11d4246cf632c97 100644 (file)
@@ -108,14 +108,13 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
 }
 
 
-/* create a port, port number or a negative error code is returned
+/* create a port, 0 on success or a negative error code is returned
  * the caller needs to unref the port via snd_seq_port_unlock() appropriately
  */
-int snd_seq_create_port(struct snd_seq_client *client, int port,
+int snd_seq_create_port(struct snd_seq_client *client,
                        struct snd_seq_client_port **port_ret)
 {
-       struct snd_seq_client_port *new_port, *p;
-       int num;
+       struct snd_seq_client_port *new_port;
        
        *port_ret = NULL;
 
@@ -141,15 +140,25 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
        port_subs_info_init(&new_port->c_dest);
        snd_use_lock_use(&new_port->use_lock);
 
+       *port_ret = new_port;
+
+       return 0;
+}
+
+/* insert the port; return the port address or a negative error code */
+int snd_seq_insert_port(struct snd_seq_client *client, int port,
+                       struct snd_seq_client_port *new_port)
+{
+       struct snd_seq_client_port *p;
+       int num;
+
        num = max(port, 0);
        guard(mutex)(&client->ports_mutex);
        guard(write_lock_irq)(&client->ports_lock);
        struct list_head *insert_before = &client->ports_list_head;
        list_for_each_entry(p, &client->ports_list_head, list) {
-               if (p->addr.port == port) {
-                       kfree(new_port);
+               if (p->addr.port == port)
                        return -EBUSY;
-               }
                if (p->addr.port > num) {
                        insert_before = &p->list;
                        break;
@@ -162,7 +171,6 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
        client->num_ports++;
        new_port->addr.port = num;      /* store the port number in the port */
        sprintf(new_port->name, "port-%d", num);
-       *port_ret = new_port;
 
        return num;
 }
index 40ed6cf7cb90bb34b4bf4fbab560e01346f78d77..b689c0f4867c445e26f6f645a11b4d0fc0c941cd 100644 (file)
@@ -98,10 +98,14 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
 
 DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T))
 
-/* create a port, port number or a negative error code is returned */
-int snd_seq_create_port(struct snd_seq_client *client, int port_index,
+/* create a port, 0 on success or a negative error code is returned */
+int snd_seq_create_port(struct snd_seq_client *client,
                        struct snd_seq_client_port **port_ret);
 
+/* insert the port; return the port address or a negative error code */
+int snd_seq_insert_port(struct snd_seq_client *client, int port,
+                       struct snd_seq_client_port *new_port);
+
 /* delete a port */
 int snd_seq_delete_port(struct snd_seq_client *client, int port);