ALSA: seq: Use flexible array for MIDI channels

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>
This commit is contained in:
Rosen Penev 2026-05-11 00:54:47 -07:00 committed by Takashi Iwai
parent 0d552587a3
commit cb02416507
4 changed files with 18 additions and 39 deletions

View 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 */

View 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 {

View 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);

View 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);
}
}