From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:37038) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TC4y5-0002i1-Vc for qemu-devel@nongnu.org; Thu, 13 Sep 2012 04:40:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TC4xz-0007GY-0U for qemu-devel@nongnu.org; Thu, 13 Sep 2012 04:40:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:64393) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TC4xy-0007E0-MT for qemu-devel@nongnu.org; Thu, 13 Sep 2012 04:40:06 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q8D8e5FD011441 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 13 Sep 2012 04:40:06 -0400 From: Gerd Hoffmann Date: Thu, 13 Sep 2012 10:39:55 +0200 Message-Id: <1347525600-28220-10-git-send-email-kraxel@redhat.com> In-Reply-To: <1347525600-28220-1-git-send-email-kraxel@redhat.com> References: <1347525600-28220-1-git-send-email-kraxel@redhat.com> Subject: [Qemu-devel] [PATCH 09/14] usb-redir: Add an already_in_flight packet-id queue List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Hans de Goede , Gerd Hoffmann From: Hans de Goede After a live migration, the usb-hcd will re-queue all packets by walking over the schedule in the guest memory again, but requests which were encountered on the migration source before will already be in flight, so these should *not* be re-send to the usbredir-host. This patch adds an already in flight packet ud queue, which will be filled by the source before migration and then moved over to the migration dest, any async handled packets are then checked against this queue to avoid sending the same packet to the usbredir-host twice. Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 603262a..f474da8 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -98,6 +98,7 @@ struct USBRedirDevice { struct usbredirparser *parser; struct endp_data endpoint[MAX_ENDPOINTS]; struct PacketIdQueue cancelled; + struct PacketIdQueue already_in_flight; /* Data for device filtering */ struct usb_redir_device_connect_header device_info; struct usb_redir_interface_info_header interface_info; @@ -316,6 +317,34 @@ static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id) return packet_id_queue_remove(&dev->cancelled, id); } +static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev, + struct USBEndpoint *ep) +{ + static USBPacket *p; + + QTAILQ_FOREACH(p, &ep->queue, queue) { + packet_id_queue_add(&dev->already_in_flight, p->id); + } +} + +static void usbredir_fill_already_in_flight(USBRedirDevice *dev) +{ + int ep; + struct USBDevice *udev = &dev->dev; + + usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_ctl); + + for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { + usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]); + usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]); + } +} + +static int usbredir_already_in_flight(USBRedirDevice *dev, uint64_t id) +{ + return packet_id_queue_remove(&dev->already_in_flight, id); +} + static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev, uint8_t ep, uint64_t id) { @@ -531,6 +560,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); + if (usbredir_already_in_flight(dev, p->id)) { + return USB_RET_ASYNC; + } + bulk_packet.endpoint = ep; bulk_packet.length = p->iov.size; bulk_packet.stream_id = 0; @@ -611,6 +644,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); + if (usbredir_already_in_flight(dev, p->id)) { + return USB_RET_ASYNC; + } + interrupt_packet.endpoint = ep; interrupt_packet.length = p->iov.size; @@ -753,6 +790,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); struct usb_redir_control_packet_header control_packet; + if (usbredir_already_in_flight(dev, p->id)) { + return USB_RET_ASYNC; + } + /* Special cases for certain standard device requests */ switch (request) { case DeviceOutRequest | USB_REQ_SET_ADDRESS: @@ -959,6 +1000,7 @@ static int usbredir_initfn(USBDevice *udev) dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev); packet_id_queue_init(&dev->cancelled, dev, "cancelled"); + packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight"); for (i = 0; i < MAX_ENDPOINTS; i++) { QTAILQ_INIT(&dev->endpoint[i].bufpq); } @@ -980,6 +1022,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) int i; packet_id_queue_empty(&dev->cancelled); + packet_id_queue_empty(&dev->already_in_flight); for (i = 0; i < MAX_ENDPOINTS; i++) { usbredir_free_bufpq(dev, I2EP(i)); } -- 1.7.1