All of lore.kernel.org
 help / color / mirror / Atom feed
From: Samuel Thibault <samuel.thibault@gnu.org>
To: Jason Andryuk <jandryuk@gmail.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [PATCH 2/4] usb-serial: chunk data to wMaxPacketSize
Date: Sat, 14 Mar 2020 01:07:46 +0100	[thread overview]
Message-ID: <20200314000746.pe5j7b2jqcbt3v7k@function> (raw)
In-Reply-To: <20200312125524.7812-3-jandryuk@gmail.com>

Jason Andryuk, le jeu. 12 mars 2020 08:55:21 -0400, a ecrit:
> usb-serial has issues with xHCI controllers where data is lost in the
> VM.  Inspecting the URBs in the guest, EHCI starts every 64 byte boundary
> (wMaxPacketSize) with a header.  EHCI hands packets into
> usb_serial_token_in() with size 64, so these cannot cross the 64 byte
> boundary.  The xHCI controller has packets of 512 bytes and the usb-serial
> will just write through the 64 byte boundary.  In the guest, this means
> data bytes are interpreted as header, so data bytes don't make it out
> the serial interface.
> 
> Re-work usb_serial_token_in to chunk data into 64 byte units - 2 byte
> header and 62 bytes data.  The Linux driver reads wMaxPacketSize to find
> the chunk size, so we match that.
> 
> Real hardware was observed to pass in 512 byte URBs (496 bytes data +
> 8 * 2 byte headers).  Since usb-serial only buffers 384 bytes of data,
> usb-serial will pass in 6 64 byte blocks and 1 12 byte partial block for
> 462 bytes max.
> 
> Signed-off-by: Jason Andryuk <jandryuk@gmail.com>

Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

> ---
>  hw/usb/dev-serial.c | 43 +++++++++++++++++++++++++++----------------
>  1 file changed, 27 insertions(+), 16 deletions(-)
> 
> diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
> index 71fa786bd8..96b6c34202 100644
> --- a/hw/usb/dev-serial.c
> +++ b/hw/usb/dev-serial.c
> @@ -360,15 +360,16 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
>  
>  static void usb_serial_token_in(USBSerialState *s, USBPacket *p)
>  {
> -    int first_len, len;
> +    const int max_packet_size = desc_iface0.eps[0].wMaxPacketSize;
> +    int packet_len;
>      uint8_t header[2];
>  
> -    first_len = RECV_BUF - s->recv_ptr;
> -    len = p->iov.size;
> -    if (len <= 2) {
> +    packet_len = p->iov.size;
> +    if (packet_len <= 2) {
>          p->status = USB_RET_NAK;
>          return;
>      }
> +
>      header[0] = usb_get_modem_lines(s) | 1;
>      /* We do not have the uart details */
>      /* handle serial break */
> @@ -380,21 +381,31 @@ static void usb_serial_token_in(USBSerialState *s, USBPacket *p)
>      } else {
>          header[1] = 0;
>      }
> -    len -= 2;
> -    if (len > s->recv_used)
> -        len = s->recv_used;
> -    if (!len) {
> +
> +    if (!s->recv_used) {
>          p->status = USB_RET_NAK;
>          return;
>      }
> -    if (first_len > len)
> -        first_len = len;
> -    usb_packet_copy(p, header, 2);
> -    usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
> -    if (len > first_len)
> -        usb_packet_copy(p, s->recv_buf, len - first_len);
> -    s->recv_used -= len;
> -    s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
> +
> +    while (s->recv_used && packet_len > 2) {
> +        int first_len, len;
> +
> +        len = MIN(packet_len, max_packet_size);
> +        len -= 2;
> +        if (len > s->recv_used)
> +            len = s->recv_used;
> +
> +        first_len = RECV_BUF - s->recv_ptr;
> +        if (first_len > len)
> +            first_len = len;
> +        usb_packet_copy(p, header, 2);
> +        usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
> +        if (len > first_len)
> +            usb_packet_copy(p, s->recv_buf, len - first_len);
> +        s->recv_used -= len;
> +        s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
> +        packet_len -= len + 2;
> +    }
>  
>      return;
>  }
> -- 
> 2.24.1
> 

-- 
Samuel
We are Pentium of Borg. Division is futile. You will be approximated.
(seen in someone's .signature)


  reply	other threads:[~2020-03-14  0:08 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-12 12:55 [PATCH 0/4] usb-serial: xHCI and timeout fixes Jason Andryuk
2020-03-12 12:55 ` [PATCH 1/4] usb-serial: Move USB_TOKEN_IN into a helper function Jason Andryuk
2020-03-13 23:56   ` Samuel Thibault
2020-03-16 11:40   ` Gerd Hoffmann
2020-03-16 12:05     ` Jason Andryuk
2020-03-12 12:55 ` [PATCH 2/4] usb-serial: chunk data to wMaxPacketSize Jason Andryuk
2020-03-14  0:07   ` Samuel Thibault [this message]
2020-03-12 12:55 ` [PATCH 3/4] usb-serial: Increase receive buffer to 496 Jason Andryuk
2020-03-14 21:40   ` Samuel Thibault
2020-03-12 12:55 ` [PATCH 4/4] usb-serial: Fix timeout closing the device Jason Andryuk
2020-03-14 21:41   ` Samuel Thibault
2020-03-12 13:14 ` [PATCH 0/4] usb-serial: xHCI and timeout fixes no-reply
2020-03-12 13:31 ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200314000746.pe5j7b2jqcbt3v7k@function \
    --to=samuel.thibault@gnu.org \
    --cc=jandryuk@gmail.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.