dcavalca / rpms / qemu

Forked from rpms/qemu 11 months ago
Clone

Blame 0362-usb-redir-Add-an-already_in_flight-packet-id-queue.patch

Hans de Goede 393f81
From b422d151d0861ed346bed7cddb410a6b4c67711b 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
Hans de Goede 393f81
Subject: [PATCH 362/365] 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
Hans de Goede c8dfc6
index 08776d9..1c8edd3 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;
Hans de Goede c8dfc6
@@ -326,6 +327,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
 {
Hans de Goede c8dfc6
@@ -541,6 +570,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;
Hans de Goede c8dfc6
@@ -621,6 +654,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
 
Hans de Goede c8dfc6
@@ -763,6 +800,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:
Hans de Goede c8dfc6
@@ -987,6 +1028,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
     }
Hans de Goede c8dfc6
@@ -1007,6 +1049,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
-- 
Hans de Goede c8dfc6
1.7.12
Hans de Goede c8dfc6