From 7c269cb9336f6b2c3200df47ed2d38e85ada8b10 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Mon, 25 Sep 2017 15:49:32 +0200 Subject: [PATCH] qemu-usb: Handle failing packet allocations gracefully * catch failed allocations * if a packet allocation fails, return NAK USB packet state * increase packet stream size to 6 MiB fixes #2527 --- repos/libports/src/lib/qemu-usb/host.cc | 38 ++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/repos/libports/src/lib/qemu-usb/host.cc b/repos/libports/src/lib/qemu-usb/host.cc index e27cda721..ad82c2885 100644 --- a/repos/libports/src/lib/qemu-usb/host.cc +++ b/repos/libports/src/lib/qemu-usb/host.cc @@ -159,7 +159,7 @@ struct Usb_host_device : List::Element unsigned bus, unsigned dev) : label(label), _alloc(&alloc), - usb_raw(env, &_alloc, label, 1024*1024, state_dispatcher), + usb_raw(env, &_alloc, label, 6*1024*1024, state_dispatcher), bus(bus), dev(dev), sig_rec(sig_rec) { usb_raw.tx_channel()->sigh_ack_avail(ack_avail_dispatcher); @@ -420,23 +420,29 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p) bool const in = p->pid == USB_TOKEN_IN; - Usb::Packet_descriptor packet = dev->alloc_packet(size); - packet.type = type; - packet.transfer.ep = p->ep->nr | (in ? USB_DIR_IN : 0); - packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL; + try { + Usb::Packet_descriptor packet = dev->alloc_packet(size); + packet.type = type; + packet.transfer.ep = p->ep->nr | (in ? USB_DIR_IN : 0); + packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL; - if (!in) { - char * const content = dev->usb_raw.source()->packet_content(packet); - usb_packet_copy(p, content, size); + if (!in) { + char * const content = dev->usb_raw.source()->packet_content(packet); + usb_packet_copy(p, content, size); + } + + Completion *c = dynamic_cast(packet.completion); + c->p = p; + c->dev = udev; + c->data = nullptr; + + dev->submit(packet); + p->status = USB_RET_ASYNC; + } catch (...) { + /* submit queue full or packet larger than packet stream */ + Genode::warning("xHCI: packet allocation failed (size ", Genode::Hex(size), ")"); + p->status = USB_RET_NAK; } - - Completion *c = dynamic_cast(packet.completion); - c->p = p; - c->dev = udev; - c->data = nullptr; - - dev->submit(packet); - p->status = USB_RET_ASYNC; }