From 19d9409a3458dd61f2d71156565f613a306df752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Mon, 25 Jan 2021 14:58:20 +0100 Subject: [PATCH] qemu-usb: adapt ISOCH IN handling for audio Linux as well as Windows guests want queue to a varying number of transfers, where each transfer only covers one transaction (iso frame). The best results were obtained by following that behaviour rather than queuing multiple iso frames per requests (like is done with OUT transfers). The number of requests queued is increased to 32 while the number of packets per reques is decreased to 1. Issue #4018. --- repos/libports/src/lib/qemu-usb/host.cc | 29 ++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/repos/libports/src/lib/qemu-usb/host.cc b/repos/libports/src/lib/qemu-usb/host.cc index fd0c302bcf..9f72cd3739 100644 --- a/repos/libports/src/lib/qemu-usb/host.cc +++ b/repos/libports/src/lib/qemu-usb/host.cc @@ -53,6 +53,9 @@ class Isoc_packet : Fifo::Element char *_content; int _size; + int _packet_index { 0 }; + unsigned _packet_in_offset { 0 }; + public: Isoc_packet(Usb::Packet_descriptor packet, char *content) @@ -79,6 +82,26 @@ class Isoc_packet : Fifo::Element return remaining <= usb_packet->iov.size; } + bool copy_read(USBPacket *usb_packet) + { + if (!valid()) return false; + + unsigned remaining = _packet.transfer.actual_packet_size[_packet_index]; + /* this should not happen as there asserts in the qemu code */ + if (remaining > usb_packet->iov.size) { + Genode::error("iov too small, ignoring packet content"); + } + int copy_size = min(usb_packet->iov.size, remaining); + + char *src = _content + _packet_in_offset; + usb_packet_copy(usb_packet, src, copy_size); + + _packet_in_offset += _packet.transfer.packet_size[_packet_index]; + ++_packet_index; + + return _packet_index == _packet.transfer.number_of_packets; + } + bool valid() const { return _content != nullptr; } unsigned packet_count() const { return _packet.transfer.number_of_packets; } @@ -345,7 +368,7 @@ struct Usb_host_device : List::Element } isoc_read_queue.head([&] (Isoc_packet &head) { - if (head.copy(packet)) { + if (head.copy_read(packet)) { isoc_read_queue.remove(head); free_packet(&head); } @@ -360,12 +383,12 @@ struct Usb_host_device : List::Element { unsigned count = 0; isoc_read_queue.for_each([&count] (Isoc_packet&) { count++; }); - return (count + _isoc_in_pending) < 3 ? true : false; + return (count + _isoc_in_pending) < 32 ? true : false; } void isoc_in_packet(USBPacket *usb_packet) { - enum { NUMBER_OF_PACKETS = 2 }; + enum { NUMBER_OF_PACKETS = 1 }; isoc_read(usb_packet); if (!isoc_new_packet())