From nobody Mon May 20 05:36:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1563973184; cv=none; d=zoho.com; s=zohoarc; b=HatbqqbKnjooxVXPVK8OdEDuwpM7ccSHU05dhxlnHygpXxqk0LFVJBwK3e9R/p+K5iskTLNHchXHTc2+NYE1SQL7Fvev0Un/1G870RpidQ0hor+xOSU85v5L9/LJsDNxlQPaxS17/ZSTIrFQ2tDHCeqhbxWJpEHZW/q/f3NStyg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563973184; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=PiH+CBX0sI+gcGrH0HJLrfPzXRe6MW+BiFDwixm7IdU=; b=oJwoNNiurcpaHIXF2YbqAUrwug5DWQKSybDj2Am/vhKFRAlY3rhFDb7dUMyieba8MSyZ4VZkOfmixiITXp5S0jRixtbkF/IcEGQidand1KnzJj3bCN0Leh7fohZPCltnQTRMMr2i6Sov/QuJ8/PdARkPnfuw3ykWaOaCZLL/3k4= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 156397318482356.52144659783528; Wed, 24 Jul 2019 05:59:44 -0700 (PDT) Received: from localhost ([::1]:51424 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hqGrr-00070U-VZ for importer@patchew.org; Wed, 24 Jul 2019 08:59:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58820) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hqGrc-0006DB-CH for qemu-devel@nongnu.org; Wed, 24 Jul 2019 08:59:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hqGrb-00016q-5s for qemu-devel@nongnu.org; Wed, 24 Jul 2019 08:59:24 -0400 Received: from 2001-1ae9-0158-5901-ecc0-4afa-64c0-20f1.ip6.tmcz.cz ([2001:1ae9:158:5901:ecc0:4afa:64c0:20f1]:49878 helo=xen3.c-home.cz) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hqGra-00016O-Or for qemu-devel@nongnu.org; Wed, 24 Jul 2019 08:59:23 -0400 Received: from xen3.c-home.cz (localhost [127.0.0.1]) by xen3.c-home.cz (8.15.2/8.15.2) with ESMTP id x6OCx5sj014849; Wed, 24 Jul 2019 14:59:20 +0200 From: Martin Cerveny To: Gerd Hoffmann Date: Wed, 24 Jul 2019 14:58:59 +0200 Message-Id: <20190724125859.14624-2-M.Cerveny@computer.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190724125859.14624-1-M.Cerveny@computer.org> References: <20190724125859.14624-1-M.Cerveny@computer.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:1ae9:158:5901:ecc0:4afa:64c0:20f1 Subject: [Qemu-devel] [PATCH 1/1] usb-redir: merge interrupt packets X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org, Martin Cerveny Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Interrupt packets (limited by wMaxPacketSize) should be buffered and merged by algorithm described in USB spec. (see usb_20.pdf/5.7.3 Interrupt Transfer Packet Size Constraints). Signed-off-by: Martin Cerveny --- hw/usb/redirect.c | 69 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 998fc6e4b0..0c0c86878c 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -815,8 +815,8 @@ static void usbredir_handle_interrupt_in_data(USBRedirD= evice *dev, USBPacket *p, uint8_t ep) { /* Input interrupt endpoint, buffered packet input */ - struct buf_packet *intp; - int status, len; + struct buf_packet *intp, *intp_to_free; + int status, len, sum; =20 if (!dev->endpoint[EP2I(ep)].interrupt_started && !dev->endpoint[EP2I(ep)].interrupt_error) { @@ -835,9 +835,17 @@ static void usbredir_handle_interrupt_in_data(USBRedir= Device *dev, dev->endpoint[EP2I(ep)].bufpq_dropping_packets =3D 0; } =20 - intp =3D QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq); + /* check for completed interrupt message (with all fragments) */ + sum =3D 0; + QTAILQ_FOREACH(intp, &dev->endpoint[EP2I(ep)].bufpq, next) { + sum +=3D intp->len; + if (intp->len < dev->endpoint[EP2I(ep)].max_packet_size || + sum >=3D p->iov.size) + break; + } + if (intp =3D=3D NULL) { - DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep); + DPRINTF2("interrupt-token-in ep %02X, no intp, buffered %d\n", ep,= sum); /* Check interrupt_error for stream errors */ status =3D dev->endpoint[EP2I(ep)].interrupt_error; dev->endpoint[EP2I(ep)].interrupt_error =3D 0; @@ -848,18 +856,42 @@ static void usbredir_handle_interrupt_in_data(USBRedi= rDevice *dev, } return; } - DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep, - intp->status, intp->len); =20 - status =3D intp->status; - len =3D intp->len; - if (len > p->iov.size) { - ERROR("received int data is larger then packet ep %02X\n", ep); - len =3D p->iov.size; - status =3D usb_redir_babble; + /* copy of completed interrupt message */ + sum =3D 0; + status =3D usb_redir_success; + intp_to_free =3D NULL; + QTAILQ_FOREACH(intp, &dev->endpoint[EP2I(ep)].bufpq, next) { + if (intp_to_free) { + bufp_free(dev, intp_to_free, ep); + } + DPRINTF("interrupt-token-in ep %02X fragment status %d len %d\n", = ep, + intp->status, intp->len); + + sum +=3D intp->len; + len =3D intp->len; + if (status =3D=3D usb_redir_success) { + status =3D intp->status; + } + if (sum > p->iov.size) { + ERROR("received int data is larger then packet ep %02X\n", ep); + len -=3D (sum - p->iov.size); + sum =3D p->iov.size; + status =3D usb_redir_babble; + } + + usb_packet_copy(p, intp->data, len); + + intp_to_free =3D intp; + if (intp->len < dev->endpoint[EP2I(ep)].max_packet_size || + sum >=3D p->iov.size) + break; } - usb_packet_copy(p, intp->data, len); - bufp_free(dev, intp, ep); + if (intp_to_free) { + bufp_free(dev, intp_to_free, ep); + } + DPRINTF("interrupt-token-in ep %02X summary status %d len %d\n", ep, + status, sum); usbredir_handle_status(dev, p, status); } =20 @@ -2032,22 +2064,17 @@ static void usbredir_interrupt_packet(void *priv, u= int64_t id, } =20 if (ep & USB_DIR_IN) { - bool q_was_empty; - if (dev->endpoint[EP2I(ep)].interrupt_started =3D=3D 0) { DPRINTF("received int packet while not started ep %02X\n", ep); free(data); return; } =20 - q_was_empty =3D QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq); - /* bufp_alloc also adds the packet to the ep queue */ bufp_alloc(dev, data, data_len, interrupt_packet->status, ep, data= ); =20 - if (q_was_empty) { - usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f), 0); - } + /* insufficient data solved with USB_RET_NAK */ + usb_wakeup(usb_ep_get(&dev->dev, USB_TOKEN_IN, ep & 0x0f), 0); } else { /* * We report output interrupt packets as completed directly upon --=20 2.20.1