From patchwork Wed Oct 24 16:14:12 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: 193927 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 D5AC62C0172 for ; Thu, 25 Oct 2012 06:24:36 +1100 (EST) Received: from localhost ([::1]:55330 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TR3as-00020F-3P for incoming@patchwork.ozlabs.org; Wed, 24 Oct 2012 12:14:10 -0400 Received: from eggs.gnu.org ([208.118.235.92]:58130) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TR3Zk-0008KA-KQ for qemu-devel@nongnu.org; Wed, 24 Oct 2012 12:13:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TR3Zi-0004mb-5S for qemu-devel@nongnu.org; Wed, 24 Oct 2012 12:13:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:9966) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TR3Zh-0004mN-SV for qemu-devel@nongnu.org; Wed, 24 Oct 2012 12:12:58 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9OGCv1o031921 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 24 Oct 2012 12:12:57 -0400 Received: from shalem.localdomain.com (vpn1-6-4.ams2.redhat.com [10.36.6.4]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q9OGCYjo008030; Wed, 24 Oct 2012 12:12:56 -0400 From: Hans de Goede To: Gerd Hoffmann Date: Wed, 24 Oct 2012 18:14:12 +0200 Message-Id: <1351095258-5579-17-git-send-email-hdegoede@redhat.com> In-Reply-To: <1351095258-5579-1-git-send-email-hdegoede@redhat.com> References: <1351095258-5579-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Hans de Goede , qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 16/22] combined-packet: Add a workaround for Linux usbfs + live migration 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 Older versions (anything but the latest) of Linux usbfs + libusb(x), will submit larger (bulk) transfers split into multiple 16k submissions, which means that rather then all tds getting linked into the queue in one atomic operarion they get linked in a bunch at a time, which could cause problems if: 1) We scan the queue while libusb is in the middle of submitting a split bulk transfer 2) While this bulk transfer is pending we migrate to another host. The problem is that after 2, the new host will rescan the queue and combine the packets in one large transfer, where as 1) has caused the original host to see them as 2 transfers. This patch fixes this by stopping combinging if we detect a 16k transfer with its int_req flag set. This should not adversely effect performance for other cases as: 1) Linux never sets the interrupt flag on packets other then the last 2) Windows does set the in_req flag on each td, but will submit large transfers in 20k tds thus never triggering the check Signed-off-by: Hans de Goede --- hw/usb/combined-packet.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c index 5f92ef9..ab23ade 100644 --- a/hw/usb/combined-packet.c +++ b/hw/usb/combined-packet.c @@ -120,7 +120,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) USBPacket *p, *u, *next, *prev = NULL, *first = NULL; USBPort *port = ep->dev->port; USBDeviceClass *klass = USB_DEVICE_GET_CLASS(ep->dev); - int ret; + int ret, totalsize; assert(ep->pipeline); assert(ep->pid == USB_TOKEN_IN); @@ -165,8 +165,11 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) } /* Is this packet the last one of a (combined) transfer? */ + totalsize = (p->combined) ? p->combined->iov.size : p->iov.size; if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok || - next == NULL) { + next == NULL || + /* Work around for Linux usbfs bulk splitting + migration */ + (totalsize == 16348 && p->int_req)) { ret = klass->handle_combined_data(ep->dev, first); assert(ret == USB_RET_ASYNC); if (first->combined) {