Skip to content

Commit

Permalink
usb-redir: Add an already_in_flight packet-id queue
Browse files Browse the repository at this point in the history
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 <hdegoede@redhat,com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
  • Loading branch information
jwrdegoede authored and kraxel committed Sep 13, 2012
1 parent 8e60452 commit 9a8d406
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions hw/usb/redirect.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}
Expand All @@ -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));
}
Expand Down

0 comments on commit 9a8d406

Please sign in to comment.