From b2bcbd031d34d1ba1f491b9152474cf9f6d4d51b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 24 Aug 2023 09:51:07 +0200 Subject: ALSA: ump: Don't create unused substreams for static blocks When the UMP Endpoint is declared as "static", that is, no dynamic reassignment of UMP Groups, it makes little sense to expose always all 16 groups with 16 substreams. Many of those substreams are disabled groups, hence they are useless, but applications don't know it and try to open / access all those substreams unnecessarily. This patch limits the number of UMP legacy rawmidi substreams only to the active groups. The behavior is changed only for the static endpoint (i.e. devices without UMP v1.1 feature implemented or with the static block flag is set). Fixes: 0b5288f5fe63 ("ALSA: ump: Add legacy raw MIDI support") Link: https://lore.kernel.org/r/20230824075108.29958-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/ump.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'sound/core') diff --git a/sound/core/ump.c b/sound/core/ump.c index d5d72473d999..cd192bec227a 100644 --- a/sound/core/ump.c +++ b/sound/core/ump.c @@ -984,7 +984,7 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream) { struct snd_ump_endpoint *ump = substream->rmidi->private_data; int dir = substream->stream; - int group = substream->number; + int group = ump->legacy_mapping[substream->number]; int err; mutex_lock(&ump->open_mutex); @@ -1016,7 +1016,7 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream) { struct snd_ump_endpoint *ump = substream->rmidi->private_data; int dir = substream->stream; - int group = substream->number; + int group = ump->legacy_mapping[substream->number]; mutex_lock(&ump->open_mutex); spin_lock_irq(&ump->legacy_locks[dir]); @@ -1123,6 +1123,34 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src, spin_unlock_irqrestore(&ump->legacy_locks[dir], flags); } +/* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */ +static int fill_legacy_mapping(struct snd_ump_endpoint *ump) +{ + struct snd_ump_block *fb; + unsigned int group_maps = 0; + int i, num; + + if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) { + list_for_each_entry(fb, &ump->block_list, list) { + for (i = 0; i < fb->info.num_groups; i++) + group_maps |= 1U << (fb->info.first_group + i); + } + if (!group_maps) + ump_info(ump, "No UMP Group is found in FB\n"); + } + + /* use all groups for non-static case */ + if (!group_maps) + group_maps = (1U << SNDRV_UMP_MAX_GROUPS) - 1; + + num = 0; + for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) + if (group_maps & (1U << i)) + ump->legacy_mapping[num++] = i; + + return num; +} + static void fill_substream_names(struct snd_ump_endpoint *ump, struct snd_rawmidi *rmidi, int dir) { @@ -1130,7 +1158,7 @@ static void fill_substream_names(struct snd_ump_endpoint *ump, list_for_each_entry(s, &rmidi->streams[dir].substreams, list) snprintf(s->name, sizeof(s->name), "Group %d (%s)", - s->number + 1, ump->info.name); + ump->legacy_mapping[s->number] + 1, ump->info.name); } int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, @@ -1138,16 +1166,19 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, { struct snd_rawmidi *rmidi; bool input, output; - int err; + int err, num; - ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL); + ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS, + sizeof(*ump->out_cvts), GFP_KERNEL); if (!ump->out_cvts) return -ENOMEM; + num = fill_legacy_mapping(ump); + input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT; output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT; err = snd_rawmidi_new(ump->core.card, id, device, - output ? 16 : 0, input ? 16 : 0, + output ? num : 0, input ? num : 0, &rmidi); if (err < 0) { kfree(ump->out_cvts); -- cgit v1.2.3