Skip to content

Commit b2bcbd0

Browse files
committed
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: 0b5288f ("ALSA: ump: Add legacy raw MIDI support") Link: https://lore.kernel.org/r/20230824075108.29958-4-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 1761f4c commit b2bcbd0

2 files changed

Lines changed: 38 additions & 6 deletions

File tree

include/sound/ump.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct snd_ump_endpoint {
4545
spinlock_t legacy_locks[2];
4646
struct snd_rawmidi *legacy_rmidi;
4747
struct snd_rawmidi_substream *legacy_substreams[2][SNDRV_UMP_MAX_GROUPS];
48+
unsigned char legacy_mapping[SNDRV_UMP_MAX_GROUPS];
4849

4950
/* for legacy output; need to open the actual substream unlike input */
5051
int legacy_out_opens;

sound/core/ump.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
984984
{
985985
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
986986
int dir = substream->stream;
987-
int group = substream->number;
987+
int group = ump->legacy_mapping[substream->number];
988988
int err;
989989

990990
mutex_lock(&ump->open_mutex);
@@ -1016,7 +1016,7 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream)
10161016
{
10171017
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
10181018
int dir = substream->stream;
1019-
int group = substream->number;
1019+
int group = ump->legacy_mapping[substream->number];
10201020

10211021
mutex_lock(&ump->open_mutex);
10221022
spin_lock_irq(&ump->legacy_locks[dir]);
@@ -1123,31 +1123,62 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
11231123
spin_unlock_irqrestore(&ump->legacy_locks[dir], flags);
11241124
}
11251125

1126+
/* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */
1127+
static int fill_legacy_mapping(struct snd_ump_endpoint *ump)
1128+
{
1129+
struct snd_ump_block *fb;
1130+
unsigned int group_maps = 0;
1131+
int i, num;
1132+
1133+
if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) {
1134+
list_for_each_entry(fb, &ump->block_list, list) {
1135+
for (i = 0; i < fb->info.num_groups; i++)
1136+
group_maps |= 1U << (fb->info.first_group + i);
1137+
}
1138+
if (!group_maps)
1139+
ump_info(ump, "No UMP Group is found in FB\n");
1140+
}
1141+
1142+
/* use all groups for non-static case */
1143+
if (!group_maps)
1144+
group_maps = (1U << SNDRV_UMP_MAX_GROUPS) - 1;
1145+
1146+
num = 0;
1147+
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++)
1148+
if (group_maps & (1U << i))
1149+
ump->legacy_mapping[num++] = i;
1150+
1151+
return num;
1152+
}
1153+
11261154
static void fill_substream_names(struct snd_ump_endpoint *ump,
11271155
struct snd_rawmidi *rmidi, int dir)
11281156
{
11291157
struct snd_rawmidi_substream *s;
11301158

11311159
list_for_each_entry(s, &rmidi->streams[dir].substreams, list)
11321160
snprintf(s->name, sizeof(s->name), "Group %d (%s)",
1133-
s->number + 1, ump->info.name);
1161+
ump->legacy_mapping[s->number] + 1, ump->info.name);
11341162
}
11351163

11361164
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
11371165
char *id, int device)
11381166
{
11391167
struct snd_rawmidi *rmidi;
11401168
bool input, output;
1141-
int err;
1169+
int err, num;
11421170

1143-
ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL);
1171+
ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS,
1172+
sizeof(*ump->out_cvts), GFP_KERNEL);
11441173
if (!ump->out_cvts)
11451174
return -ENOMEM;
11461175

1176+
num = fill_legacy_mapping(ump);
1177+
11471178
input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT;
11481179
output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT;
11491180
err = snd_rawmidi_new(ump->core.card, id, device,
1150-
output ? 16 : 0, input ? 16 : 0,
1181+
output ? num : 0, input ? num : 0,
11511182
&rmidi);
11521183
if (err < 0) {
11531184
kfree(ump->out_cvts);

0 commit comments

Comments
 (0)