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 <[email protected]>
---
 include/sound/emux_synth.h     |  2 +-
 include/sound/seq_midi_emul.h  |  6 +++---
 sound/core/seq/seq_midi_emul.c | 38 ++++++++++------------------------
 sound/synth/emux/emux_seq.c    | 11 +++-------
 4 files changed, 18 insertions(+), 39 deletions(-)

diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h
index 3f7f365ed248..2c0a976e00ab 100644
--- a/include/sound/emux_synth.h
+++ b/include/sound/emux_synth.h
@@ -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 */
diff --git a/include/sound/seq_midi_emul.h b/include/sound/seq_midi_emul.h
index 88799d1e1f53..afc765437870 100644
--- a/include/sound/seq_midi_emul.h
+++ b/include/sound/seq_midi_emul.h
@@ -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 {
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index fd067c85c524..a90ebc7b3811 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -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);
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 2ed01e9d79bb..01ad5b12b680 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -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);
        }
 }
-- 
2.54.0


Reply via email to