From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 28/28] xhci: handle USB_RET_NAK
Date: Fri, 10 Feb 2012 12:43:24 +0100 [thread overview]
Message-ID: <1328874204-20920-29-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1328874204-20920-1-git-send-email-kraxel@redhat.com>
Add a field to XHCITransfer to correctly keep track of NAK'ed usb
packets. Retry transfers when the endpoint is kicked again. Implement
wakeup_endpoint bus op so we can kick the endpoint when needed.
With this patch applied the emulated hid devices are working correctly
when hooked up to xhci. usb-tabled without polling, yay!
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb-xhci.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c
index 3026edb..ac7b12b 100644
--- a/hw/usb-xhci.c
+++ b/hw/usb-xhci.c
@@ -307,7 +307,8 @@ typedef struct XHCIState XHCIState;
typedef struct XHCITransfer {
XHCIState *xhci;
USBPacket packet;
- bool running;
+ bool running_async;
+ bool running_retry;
bool cancelled;
bool complete;
bool backgrounded;
@@ -338,6 +339,7 @@ typedef struct XHCIEPContext {
unsigned int next_xfer;
unsigned int comp_xfer;
XHCITransfer transfers[TD_QUEUE];
+ XHCITransfer *retry;
bool bg_running;
bool bg_updating;
unsigned int next_bg;
@@ -915,12 +917,17 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
xferi = epctx->next_xfer;
for (i = 0; i < TD_QUEUE; i++) {
XHCITransfer *t = &epctx->transfers[xferi];
- if (t->running) {
+ if (t->running_async) {
+ usb_cancel_packet(&t->packet);
+ t->running_async = 0;
t->cancelled = 1;
- /* libusb_cancel_transfer(t->usbxfer) */
DPRINTF("xhci: cancelling transfer %d, waiting for it to complete...\n", i);
killed++;
}
+ if (t->running_retry) {
+ t->running_retry = 0;
+ epctx->retry = NULL;
+ }
if (t->backgrounded) {
t->backgrounded = 0;
}
@@ -941,9 +948,10 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
xferi = epctx->next_bg;
for (i = 0; i < BG_XFERS; i++) {
XHCITransfer *t = &epctx->bg_transfers[xferi];
- if (t->running) {
+ if (t->running_async) {
+ usb_cancel_packet(&t->packet);
+ t->running_async = 0;
t->cancelled = 1;
- /* libusb_cancel_transfer(t->usbxfer); */
DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
killed++;
}
@@ -1409,12 +1417,20 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
static int xhci_complete_packet(XHCITransfer *xfer, int ret)
{
if (ret == USB_RET_ASYNC) {
- xfer->running = 1;
+ xfer->running_async = 1;
+ xfer->running_retry = 0;
+ xfer->complete = 0;
+ xfer->cancelled = 0;
+ return 0;
+ } else if (ret == USB_RET_NAK) {
+ xfer->running_async = 0;
+ xfer->running_retry = 1;
xfer->complete = 0;
xfer->cancelled = 0;
return 0;
} else {
- xfer->running = 0;
+ xfer->running_async = 0;
+ xfer->running_retry = 0;
xfer->complete = 1;
}
@@ -1529,7 +1545,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
wValue, wIndex, wLength, xfer->data);
xhci_complete_packet(xfer, ret);
- if (!xfer->running) {
+ if (!xfer->running_async && !xfer->running_retry) {
xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
}
return 0;
@@ -1596,7 +1612,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
ret = usb_handle_packet(dev, &xfer->packet);
xhci_complete_packet(xfer, ret);
- if (!xfer->running) {
+ if (!xfer->running_async && !xfer->running_retry) {
xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
}
return 0;
@@ -1667,6 +1683,25 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
return;
}
+ if (epctx->retry) {
+ /* retry nak'ed transfer */
+ XHCITransfer *xfer = epctx->retry;
+ int result;
+
+ DPRINTF("xhci: retry nack'ed transfer ...\n");
+ assert(xfer->running_retry);
+ xhci_setup_packet(xfer, xfer->packet.ep->dev);
+ result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+ if (result == USB_RET_NAK) {
+ DPRINTF("xhci: ... xfer still nacked\n");
+ return;
+ }
+ DPRINTF("xhci: ... result %d\n", result);
+ xhci_complete_packet(xfer, result);
+ assert(!xfer->running_retry);
+ epctx->retry = NULL;
+ }
+
if (epctx->state == EP_HALTED) {
DPRINTF("xhci: ep halted, not running schedule\n");
return;
@@ -1676,9 +1711,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
while (1) {
XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
- if (xfer->running || xfer->backgrounded) {
- DPRINTF("xhci: ep is busy\n");
+ if (xfer->running_async || xfer->running_retry || xfer->backgrounded) {
+ DPRINTF("xhci: ep is busy (#%d,%d,%d,%d)\n",
+ epctx->next_xfer, xfer->running_async,
+ xfer->running_retry, xfer->backgrounded);
break;
+ } else {
+ DPRINTF("xhci: ep: using #%d\n", epctx->next_xfer);
}
length = xhci_ring_chain_length(xhci, &epctx->ring);
if (length < 0) {
@@ -1725,6 +1764,11 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
DPRINTF("xhci: ep halted, stopping schedule\n");
break;
}
+ if (xfer->running_retry) {
+ DPRINTF("xhci: xfer nacked, stopping schedule\n");
+ epctx->retry = xfer;
+ break;
+ }
/*
* Qemu usb can't handle multiple in-flight xfers.
@@ -2739,7 +2783,48 @@ static USBPortOps xhci_port_ops = {
.child_detach = xhci_child_detach,
};
+static int xhci_find_slotid(XHCIState *xhci, USBDevice *dev)
+{
+ XHCISlot *slot;
+ int slotid;
+
+ for (slotid = 1; slotid <= MAXSLOTS; slotid++) {
+ slot = &xhci->slots[slotid-1];
+ if (slot->devaddr == dev->addr) {
+ return slotid;
+ }
+ }
+ return 0;
+}
+
+static int xhci_find_epid(USBEndpoint *ep)
+{
+ if (ep->nr == 0) {
+ return 1;
+ }
+ if (ep->pid == USB_TOKEN_IN) {
+ return ep->nr * 2 + 1;
+ } else {
+ return ep->nr * 2;
+ }
+}
+
+static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep)
+{
+ XHCIState *xhci = container_of(bus, XHCIState, bus);
+ int slotid;
+
+ DPRINTF("%s\n", __func__);
+ slotid = xhci_find_slotid(xhci, ep->dev);
+ if (slotid == 0 || !xhci->slots[slotid-1].enabled) {
+ DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
+ return;
+ }
+ xhci_kick_ep(xhci, slotid, xhci_find_epid(ep));
+}
+
static USBBusOps xhci_bus_ops = {
+ .wakeup_endpoint = xhci_wakeup_endpoint,
};
static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
--
1.7.1
next prev parent reply other threads:[~2012-02-10 11:44 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-10 11:42 [Qemu-devel] [PULL 00/28] usb patch queue Gerd Hoffmann
2012-02-10 11:42 ` [Qemu-devel] [PATCH 01/28] usb-uhci: implement bandwidth management Gerd Hoffmann
2012-02-10 11:42 ` [Qemu-devel] [PATCH 02/28] usb-ehci: Clear the portstatus powner bit on device disconnect Gerd Hoffmann
2012-02-10 11:42 ` [Qemu-devel] [PATCH 03/28] usb-redir: Add the posibility to filter out certain devices from redirecion Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 04/28] usb: kill USB_MSG_{ATTACH,DETACH} Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 05/28] usb: kill USB_MSG_RESET Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 06/28] usb: kill usb_send_msg Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 07/28] usb: add usb_find_device() Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 08/28] usb-hub: implement find_device Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 09/28] usb: handle dev == NULL in usb_handle_packet() Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 10/28] usb-uhci: switch to usb_find_device() Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 11/28] usb-ehci: " Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 12/28] usb-ohci: " Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 13/28] usb-musb: " Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 14/28] usb-xhci: " Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 15/28] usb: kill handle_packet callback Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 16/28] usb: fold usb_generic_handle_packet into usb_handle_packet Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 17/28] usb: USBPacket: add status, rename owner -> ep Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 18/28] usb: add USBEndpoint->{nr,pid} Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 19/28] usb: Set USBEndpoint in usb_packet_setup() Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 20/28] usb: maintain async packet list per endpoint Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 21/28] usb: pass USBEndpoint to usb_wakeup Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 22/28] usb: add USBBusOps->wakeup_endpoint Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 23/28] xhci: signal low- and fullspeed support Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 24/28] xhci: add trb type name lookup support Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 25/28] xhci: stop on errors Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 26/28] xhci: kill port arg from xhci_setup_packet Gerd Hoffmann
2012-02-10 11:43 ` [Qemu-devel] [PATCH 27/28] xhci: remote wakeup support Gerd Hoffmann
2012-02-10 11:43 ` Gerd Hoffmann [this message]
2012-02-16 0:32 ` [Qemu-devel] [PULL 00/28] 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=1328874204-20920-29-git-send-email-kraxel@redhat.com \
--to=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 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).