]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ALSA: seq: Use flexible array for MIDI channels
authorRosen Penev <rosenp@gmail.com>
Mon, 11 May 2026 07:54:47 +0000 (00:54 -0700)
committerTakashi Iwai <tiwai@suse.de>
Fri, 15 May 2026 06:52:44 +0000 (08:52 +0200)
Store MIDI channel entries in the MIDI channel set allocation instead
of allocating them separately.

This ties the channel array lifetime directly to the channel set, removes
a separate allocation failure path, and lets __counted_by() describe the
array bounds. Move the embedded emux channel set to the end of its
containing structure so it can carry the flexible array.

Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260511075447.445350-1-rosenp@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/emux_synth.h
include/sound/seq_midi_emul.h
sound/core/seq/seq_midi_emul.c
sound/synth/emux/emux_seq.c

index 3f7f365ed248cd82c0fd96c0414ccfdc2c4079ae..2c0a976e00abb4d20b94fd4df64cec370a29333e 100644 (file)
@@ -125,7 +125,6 @@ struct snd_emux {
  */
 struct snd_emux_port {
 
-       struct snd_midi_channel_set chset;
        struct snd_emux *emu;
 
        char port_mode;                 /* operation mode */
@@ -138,6 +137,7 @@ struct snd_emux_port {
 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
        struct snd_seq_oss_arg *oss_arg;
 #endif
+       struct snd_midi_channel_set chset;
 };
 
 /* port_mode */
index 88799d1e1f53dfb695919241576213700757fa9f..afc7654378701e0f00ecf40320e53ce624f1fd93 100644 (file)
@@ -55,14 +55,14 @@ struct snd_midi_channel_set {
        int  client;                    /* Client for this port */
        int  port;                      /* The port number */
 
-       int  max_channels;              /* Size of the channels array */
-       struct snd_midi_channel *channels;
-
        unsigned char midi_mode;        /* MIDI operating mode */
        unsigned char gs_master_volume; /* SYSEX master volume: 0-127 */
        unsigned char gs_chorus_mode;
        unsigned char gs_reverb_mode;
 
+       int  max_channels;              /* Size of the channels array */
+       struct snd_midi_channel channels[] __counted_by(max_channels);
+
 };
 
 struct snd_midi_op {
index fd067c85c524fcdc566fba1fc62bd8c4a151e657..a90ebc7b3811b24fc0aabf78698bdd0367d0860e 100644 (file)
@@ -81,9 +81,6 @@ snd_midi_process_event(const struct snd_midi_op *ops,
                pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n");
                return;
        }
-       if (chanset->channels == NULL)
-               return;
-
        if (snd_seq_ev_is_channel_type(ev)) {
                dest_channel = ev->data.note.channel;
                if (dest_channel >= chanset->max_channels) {
@@ -642,23 +639,6 @@ static void snd_midi_channel_init(struct snd_midi_channel *p, int n)
                p->drum_channel = 1;    /* Default ch 10 as drums */
 }
 
-/*
- * Allocate and initialise a set of midi channel control blocks.
- */
-static struct snd_midi_channel *snd_midi_channel_init_set(int n)
-{
-       struct snd_midi_channel *chan;
-       int  i;
-
-       chan = kmalloc_objs(struct snd_midi_channel, n);
-       if (chan) {
-               for (i = 0; i < n; i++)
-                       snd_midi_channel_init(chan+i, i);
-       }
-
-       return chan;
-}
-
 /*
  * reset all midi channels
  */
@@ -687,13 +667,18 @@ reset_all_channels(struct snd_midi_channel_set *chset)
 struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
 {
        struct snd_midi_channel_set *chset;
+       int i;
+
+       chset = kmalloc_flex(*chset, channels, n);
+       if (!chset)
+               return NULL;
+
+       chset->max_channels = n;
+       chset->private_data = NULL;
+
+       for (i = 0; i < n; i++)
+               snd_midi_channel_init(&chset->channels[i], i);
 
-       chset = kmalloc_obj(*chset);
-       if (chset) {
-               chset->channels = snd_midi_channel_init_set(n);
-               chset->private_data = NULL;
-               chset->max_channels = n;
-       }
        return chset;
 }
 EXPORT_SYMBOL(snd_midi_channel_alloc_set);
@@ -717,7 +702,6 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
 {
        if (chset == NULL)
                return;
-       kfree(chset->channels);
        kfree(chset);
 }
 EXPORT_SYMBOL(snd_midi_channel_free_set);
index 2ed01e9d79bb9057142baafa7625db0c3d054077..01ad5b12b680f5d13b018795f7ab8f92088e4c4a 100644 (file)
@@ -132,19 +132,15 @@ snd_emux_create_port(struct snd_emux *emu, char *name,
        int i, type, cap;
 
        /* Allocate structures for this channel */
-       p = kzalloc_obj(*p);
+       p = kzalloc_flex(*p, chset.channels, max_channels);
        if (!p)
                return NULL;
 
-       p->chset.channels = kzalloc_objs(*p->chset.channels, max_channels);
-       if (!p->chset.channels) {
-               kfree(p);
-               return NULL;
-       }
+       p->chset.max_channels = max_channels;
+
        for (i = 0; i < max_channels; i++)
                p->chset.channels[i].number = i;
        p->chset.private_data = p;
-       p->chset.max_channels = max_channels;
        p->emu = emu;
        p->chset.client = emu->client;
 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
@@ -182,7 +178,6 @@ free_port(void *private_data)
 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
                snd_emux_delete_effect(p);
 #endif
-               kfree(p->chset.channels);
                kfree(p);
        }
 }