From patchwork Sat Nov 17 11:26:57 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 199835 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0A43E2C0081 for ; Sat, 17 Nov 2012 22:25:32 +1100 (EST) Received: from localhost ([::1]:59724 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TZgWg-0002mG-4U for incoming@patchwork.ozlabs.org; Sat, 17 Nov 2012 06:25:30 -0500 Received: from eggs.gnu.org ([208.118.235.92]:43311) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TZgWV-0002W1-G3 for qemu-devel@nongnu.org; Sat, 17 Nov 2012 06:25:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TZgWS-00012d-9T for qemu-devel@nongnu.org; Sat, 17 Nov 2012 06:25:19 -0500 Received: from mx1.redhat.com ([209.132.183.28]:31497) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TZgWS-00010n-2L for qemu-devel@nongnu.org; Sat, 17 Nov 2012 06:25:16 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qAHBPCSx001884 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sat, 17 Nov 2012 06:25:13 -0500 Received: from shalem.localdomain.com (vpn1-5-33.ams2.redhat.com [10.36.5.33]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id qAHBOwMj013850; Sat, 17 Nov 2012 06:25:01 -0500 From: Hans de Goede To: Gerd Hoffmann Date: Sat, 17 Nov 2012 12:26:57 +0100 Message-Id: <1353151617-25804-3-git-send-email-hdegoede@redhat.com> In-Reply-To: <1353151617-25804-1-git-send-email-hdegoede@redhat.com> References: <1353151617-25804-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Hans de Goede , qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 2/2] usb-redir: Don't handle interrupt output packets async X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Instead report them as successfully completed directly on submission, this has 2 advantages: 1) This matches the timing of interrupt output packets on real hardware, with the previous async handling, if an ep has an interval of say 500 ms, then there would be 500+ ms between the submission and the guest seeing the completion, as we wont do the write back until the qh gets polled again. And in the mean time the guest may very well have timed out, as the guest can reasonable expect a much quicker completion. 2) This fixes interrupt output packets potentially getting send twice surrounding a migration. As we delay the writeback to guest memory until the qh gets polled again, there is a window between completion and writeback where migration can happen, in this case the destination will not know about the completion, and it will execute the packet *again* But it does also come with a disadvantage: 1) If the actual interrupt out to the real usb device fails, there is no way to report this back to the guest. This patch assumes however that interrupt outs in practice never fail, as they are only used by specialized drivers, which are unlikely to issue illegal requests (unlike general class drivers which often issue requests which some devices don't implement). And that thus the advantages outway the disadvantage. Signed-off-by: Hans de Goede --- hw/usb/redirect.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 9658bda..15f394c 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -672,21 +672,22 @@ static void usbredir_handle_interrupt_in_data(USBRedirDevice *dev, usbredir_handle_status(dev, p, status); } +/* + * Handle interrupt out data, the usbredir protocol expects us to do this + * async, so that it can report back a completion status. But guests will + * expect immediate completion for an interrupt endpoint, and handling this + * async causes migration issues. So we report success directly, counting + * on the fact that output interrupt packets normally always succeed. + */ static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev, USBPacket *p, uint8_t ep) { - /* Output interrupt endpoint, normal async operation */ struct usb_redir_interrupt_packet_header interrupt_packet; uint8_t buf[p->iov.size]; DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id); - if (usbredir_already_in_flight(dev, p->id)) { - p->status = USB_RET_ASYNC; - return; - } - interrupt_packet.endpoint = ep; interrupt_packet.length = p->iov.size; @@ -695,7 +696,6 @@ static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev, usbredirparser_send_interrupt_packet(dev->parser, p->id, &interrupt_packet, buf, p->iov.size); usbredirparser_do_write(dev->parser); - p->status = USB_RET_ASYNC; } static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev, @@ -1670,11 +1670,13 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, /* bufp_alloc also adds the packet to the ep queue */ bufp_alloc(dev, data, data_len, interrupt_packet->status, ep); } else { - USBPacket *p = usbredir_find_packet_by_id(dev, ep, id); - if (p) { - usbredir_handle_status(dev, p, interrupt_packet->status); - p->actual_length = interrupt_packet->length; - usb_packet_complete(&dev->dev, p); + /* + * We report output interrupt packets as completed directly upon + * submission, so all we can do here if one failed is warn. + */ + if (interrupt_packet->status) { + WARNING("interrupt output failed status %d ep %02X id %"PRIu64"\n", + interrupt_packet->status, ep, id); } } }