From: Cássio Gabriel Date: Mon, 23 Mar 2026 13:46:24 +0000 (-0300) Subject: ALSA: usb-audio: rotate standard MIDI output port scan X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a213b6b019519063ce10569b19da20eac6ab884f;p=thirdparty%2Flinux.git ALSA: usb-audio: rotate standard MIDI output port scan snd_usbmidi_standard_output() iterates output ports in ascending order and drains each active port until the URB is full. On interfaces where multiple USB-MIDI cables share one endpoint, sustained traffic on a lower-numbered port can consume every refill before higher-numbered ports are even examined. That behavior dates back to the original implementation and still applies with the current multi-URB output path. snd_usbmidi_do_output() can refill several idle URBs in one pass, but each refill restarts the scan at port 0, so a busy lower-numbered port can keep higher-numbered ports from making progress at all. Use ep->current_port as the starting point of the scan and advance it after each URB fill. This keeps the existing packet formatting and per-port state handling intact while preventing persistent starvation of higher-numbered ports. Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260323-usbmidi-port-fairness-v1-1-2d68e97592a1@gmail.com Signed-off-by: Takashi Iwai --- diff --git a/sound/usb/midi.c b/sound/usb/midi.c index a8bddc90c0ed6..0a5b8941ebdaa 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -699,15 +699,18 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port *port, static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep, struct urb *urb) { - int p; + int port0 = ep->current_port; + int i; + + for (i = 0; i < 0x10; ++i) { + int portnum = (port0 + i) & 15; + struct usbmidi_out_port *port = &ep->ports[portnum]; - /* FIXME: lower-numbered ports can starve higher-numbered ports */ - for (p = 0; p < 0x10; ++p) { - struct usbmidi_out_port *port = &ep->ports[p]; if (!port->active) continue; while (urb->transfer_buffer_length + 3 < ep->max_transfer) { uint8_t b; + if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) { port->active = 0; break; @@ -715,6 +718,7 @@ static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint *ep, snd_usbmidi_transmit_byte(port, b, urb); } } + ep->current_port = (port0 + 1) & 15; } static const struct usb_protocol_ops snd_usbmidi_standard_ops = {