|
|
5544c1 |
From 9a38bd644b97a4a3ae92c9246bdcdd09ba937ae8 Mon Sep 17 00:00:00 2001
|
|
Hans de Goede |
c8dfc6 |
From: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
c8dfc6 |
Date: Tue, 4 Sep 2012 17:03:54 +0200
|
|
|
5544c1 |
Subject: [PATCH] usb-redir: Add an already_in_flight packet-id queue
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
After a live migration, the usb-hcd will re-queue all packets by
|
|
Hans de Goede |
c8dfc6 |
walking over the schedule in the guest memory again, but requests which
|
|
Hans de Goede |
c8dfc6 |
were encountered on the migration source before will already be in flight,
|
|
Hans de Goede |
c8dfc6 |
so these should *not* be re-send to the usbredir-host.
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
This patch adds an already in flight packet ud queue, which will be filled by
|
|
Hans de Goede |
c8dfc6 |
the source before migration and then moved over to the migration dest, any
|
|
Hans de Goede |
c8dfc6 |
async handled packets are then checked against this queue to avoid sending
|
|
Hans de Goede |
c8dfc6 |
the same packet to the usbredir-host twice.
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
Signed-off-by: Hans de Goede <hdegoede@redhat,com>
|
|
Hans de Goede |
c8dfc6 |
---
|
|
Hans de Goede |
c8dfc6 |
hw/usb/redirect.c | 43 +++++++++++++++++++++++++++++++++++++++++++
|
|
Hans de Goede |
c8dfc6 |
1 file changed, 43 insertions(+)
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
|
|
|
5544c1 |
index e2b8159..cdd705f 100644
|
|
Hans de Goede |
c8dfc6 |
--- a/hw/usb/redirect.c
|
|
Hans de Goede |
c8dfc6 |
+++ b/hw/usb/redirect.c
|
|
Hans de Goede |
c8dfc6 |
@@ -98,6 +98,7 @@ struct USBRedirDevice {
|
|
Hans de Goede |
c8dfc6 |
struct usbredirparser *parser;
|
|
Hans de Goede |
c8dfc6 |
struct endp_data endpoint[MAX_ENDPOINTS];
|
|
Hans de Goede |
c8dfc6 |
struct PacketIdQueue cancelled;
|
|
Hans de Goede |
c8dfc6 |
+ struct PacketIdQueue already_in_flight;
|
|
Hans de Goede |
c8dfc6 |
/* Data for device filtering */
|
|
Hans de Goede |
c8dfc6 |
struct usb_redir_device_connect_header device_info;
|
|
Hans de Goede |
c8dfc6 |
struct usb_redir_interface_info_header interface_info;
|
|
|
5544c1 |
@@ -328,6 +329,34 @@ static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id)
|
|
Hans de Goede |
c8dfc6 |
return packet_id_queue_remove(&dev->cancelled, id);
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
+static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev,
|
|
Hans de Goede |
c8dfc6 |
+ struct USBEndpoint *ep)
|
|
Hans de Goede |
c8dfc6 |
+{
|
|
Hans de Goede |
c8dfc6 |
+ static USBPacket *p;
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ QTAILQ_FOREACH(p, &ep->queue, queue) {
|
|
Hans de Goede |
c8dfc6 |
+ packet_id_queue_add(&dev->already_in_flight, p->id);
|
|
Hans de Goede |
c8dfc6 |
+ }
|
|
Hans de Goede |
c8dfc6 |
+}
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+static void usbredir_fill_already_in_flight(USBRedirDevice *dev)
|
|
Hans de Goede |
c8dfc6 |
+{
|
|
Hans de Goede |
c8dfc6 |
+ int ep;
|
|
Hans de Goede |
c8dfc6 |
+ struct USBDevice *udev = &dev->dev;
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_ctl);
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+ for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
|
Hans de Goede |
c8dfc6 |
+ usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_in[ep]);
|
|
Hans de Goede |
c8dfc6 |
+ usbredir_fill_already_in_flight_from_ep(dev, &udev->ep_out[ep]);
|
|
Hans de Goede |
c8dfc6 |
+ }
|
|
Hans de Goede |
c8dfc6 |
+}
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
+static int usbredir_already_in_flight(USBRedirDevice *dev, uint64_t id)
|
|
Hans de Goede |
c8dfc6 |
+{
|
|
Hans de Goede |
c8dfc6 |
+ return packet_id_queue_remove(&dev->already_in_flight, id);
|
|
Hans de Goede |
c8dfc6 |
+}
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
|
|
Hans de Goede |
c8dfc6 |
uint8_t ep, uint64_t id)
|
|
Hans de Goede |
c8dfc6 |
{
|
|
|
5544c1 |
@@ -543,6 +572,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id);
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
+ if (usbredir_already_in_flight(dev, p->id)) {
|
|
Hans de Goede |
c8dfc6 |
+ return USB_RET_ASYNC;
|
|
Hans de Goede |
c8dfc6 |
+ }
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
bulk_packet.endpoint = ep;
|
|
Hans de Goede |
c8dfc6 |
bulk_packet.length = p->iov.size;
|
|
Hans de Goede |
c8dfc6 |
bulk_packet.stream_id = 0;
|
|
|
5544c1 |
@@ -623,6 +656,10 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
|
|
Hans de Goede |
c8dfc6 |
DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
|
|
Hans de Goede |
c8dfc6 |
p->iov.size, p->id);
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
+ if (usbredir_already_in_flight(dev, p->id)) {
|
|
Hans de Goede |
c8dfc6 |
+ return USB_RET_ASYNC;
|
|
Hans de Goede |
c8dfc6 |
+ }
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
interrupt_packet.endpoint = ep;
|
|
Hans de Goede |
c8dfc6 |
interrupt_packet.length = p->iov.size;
|
|
Hans de Goede |
c8dfc6 |
|
|
|
5544c1 |
@@ -765,6 +802,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
|
|
Hans de Goede |
c8dfc6 |
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
|
|
Hans de Goede |
c8dfc6 |
struct usb_redir_control_packet_header control_packet;
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
+ if (usbredir_already_in_flight(dev, p->id)) {
|
|
Hans de Goede |
c8dfc6 |
+ return USB_RET_ASYNC;
|
|
Hans de Goede |
c8dfc6 |
+ }
|
|
Hans de Goede |
c8dfc6 |
+
|
|
Hans de Goede |
c8dfc6 |
/* Special cases for certain standard device requests */
|
|
Hans de Goede |
c8dfc6 |
switch (request) {
|
|
Hans de Goede |
c8dfc6 |
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
|
|
|
5544c1 |
@@ -982,6 +1023,7 @@ static int usbredir_initfn(USBDevice *udev)
|
|
Hans de Goede |
c8dfc6 |
dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
packet_id_queue_init(&dev->cancelled, dev, "cancelled");
|
|
Hans de Goede |
c8dfc6 |
+ packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight");
|
|
Hans de Goede |
c8dfc6 |
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
|
Hans de Goede |
c8dfc6 |
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
|
Hans de Goede |
c8dfc6 |
}
|
|
|
5544c1 |
@@ -1002,6 +1044,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
|
|
Hans de Goede |
c8dfc6 |
int i;
|
|
Hans de Goede |
c8dfc6 |
|
|
Hans de Goede |
c8dfc6 |
packet_id_queue_empty(&dev->cancelled);
|
|
Hans de Goede |
c8dfc6 |
+ packet_id_queue_empty(&dev->already_in_flight);
|
|
Hans de Goede |
c8dfc6 |
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
|
Hans de Goede |
c8dfc6 |
usbredir_free_bufpq(dev, I2EP(i));
|
|
Hans de Goede |
c8dfc6 |
}
|
|
Hans de Goede |
c8dfc6 |
--
|
|
|
5544c1 |
1.7.12.1
|
|
Hans de Goede |
c8dfc6 |
|