From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 7/9] hw/usb-ohci: Honour endpoint maximum packet size
Date: Thu, 13 Oct 2011 13:08:29 +0200 [thread overview]
Message-ID: <1318504111-15309-8-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1318504111-15309-1-git-send-email-kraxel@redhat.com>
From: Peter Maydell <peter.maydell@linaro.org>
Honour the maximum packet size for endpoints; this applies when
sending non-isochronous data and means we transfer only as
much as the endpoint allows, leaving the transfer descriptor
on the list for another go next time around. This allows
usb-net to work when connected to an OHCI controller model.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-ohci.c | 37 +++++++++++++++++++++++++++----------
1 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index e14ced8..c2981c5 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -872,7 +872,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
{
int dir;
- size_t len = 0;
+ size_t len = 0, pktlen = 0;
#ifdef DEBUG_PACKET
const char *str = NULL;
#endif
@@ -940,20 +940,30 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
len = (td.be - td.cbp) + 1;
}
- if (len && dir != OHCI_TD_DIR_IN && !completion) {
- ohci_copy_td(ohci, &td, ohci->usb_buf, len, 0);
+ pktlen = len;
+ if (len && dir != OHCI_TD_DIR_IN) {
+ /* The endpoint may not allow us to transfer it all now */
+ pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
+ if (pktlen > len) {
+ pktlen = len;
+ }
+ if (!completion) {
+ ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 0);
+ }
}
}
flag_r = (td.flags & OHCI_TD_R) != 0;
#ifdef DEBUG_PACKET
- DPRINTF(" TD @ 0x%.8x %" PRId64 " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
- addr, (int64_t)len, str, flag_r, td.cbp, td.be);
+ DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64
+ " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
+ addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be);
- if (len > 0 && dir != OHCI_TD_DIR_IN) {
+ if (pktlen > 0 && dir != OHCI_TD_DIR_IN) {
DPRINTF(" data:");
- for (i = 0; i < len; i++)
+ for (i = 0; i < pktlen; i++) {
printf(" %.2x", ohci->usb_buf[i]);
+ }
DPRINTF("\n");
}
#endif
@@ -982,7 +992,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
usb_packet_setup(&ohci->usb_packet, pid,
OHCI_BM(ed->flags, ED_FA),
OHCI_BM(ed->flags, ED_EN));
- usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
+ usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
ret = usb_handle_packet(dev, &ohci->usb_packet);
if (ret != USB_RET_NODEV)
break;
@@ -1005,12 +1015,12 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
DPRINTF("\n");
#endif
} else {
- ret = len;
+ ret = pktlen;
}
}
/* Writeback */
- if (ret == len || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
+ if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
/* Transmission succeeded. */
if (ret == len) {
td.cbp = 0;
@@ -1026,6 +1036,12 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
OHCI_SET_BM(td.flags, TD_EC, 0);
+ if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
+ /* Partial packet transfer: TD not ready to retire yet */
+ goto exit_no_retire;
+ }
+
+ /* Setting ED_C is part of the TD retirement process */
ed->head &= ~OHCI_ED_C;
if (td.flags & OHCI_TD_T0)
ed->head |= OHCI_ED_C;
@@ -1066,6 +1082,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
i = OHCI_BM(td.flags, TD_DI);
if (i < ohci->done_count)
ohci->done_count = i;
+exit_no_retire:
ohci_put_td(ohci, addr, &td);
return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
}
--
1.7.1
next prev parent reply other threads:[~2011-10-13 11:08 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 1/9] usb-storage: fix NULL pointer dereference Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 2/9] usb-hub: need to check dev->attached Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 3/9] usb: fix port reset Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 4/9] usb-host: factor out code Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 5/9] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 6/9] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition Gerd Hoffmann
2011-10-13 11:08 ` Gerd Hoffmann [this message]
2011-10-13 11:08 ` [Qemu-devel] [PATCH 8/9] usb-hid: activate usb tablet / mouse after migration Gerd Hoffmann
2011-10-13 11:08 ` [Qemu-devel] [PATCH 9/9] usb-hub: don't trigger assert on packet completion Gerd Hoffmann
2011-10-13 11:34 ` Gerd Hoffmann
2011-10-14 16:25 ` [Qemu-devel] [PULL] usb patch queue Anthony Liguori
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=1318504111-15309-8-git-send-email-kraxel@redhat.com \
--to=kraxel@redhat.com \
--cc=peter.maydell@linaro.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).