qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Hans de Goede <hdegoede@redhat.com>, Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 11/36] usb: Add USB_RET_ADD_TO_QUEUE packet result code
Date: Thu, 25 Oct 2012 14:51:44 +0200	[thread overview]
Message-ID: <1351169529-10799-12-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1351169529-10799-1-git-send-email-kraxel@redhat.com>

From: Hans de Goede <hdegoede@redhat.com>

This can be used by usb-device code which wishes to process an entire endpoint
queue at once, to do this the usb-device code returns USB_RET_ADD_TO_QUEUE
from its handle_data class method and defines a flush_ep_queue class method
to call when the hcd is done queuing up packets.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.h          |   21 +++++++++++++++------
 hw/usb/bus.c      |    8 ++++++++
 hw/usb/core.c     |    4 ++++
 hw/usb/hcd-ehci.c |    4 ++++
 hw/usb/hcd-musb.c |    1 +
 hw/usb/hcd-ohci.c |    2 ++
 hw/usb/hcd-uhci.c |   16 +++++++++++-----
 hw/usb/hcd-xhci.c |    6 ++++++
 8 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/hw/usb.h b/hw/usb.h
index 01dd423..435cd42 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -38,12 +38,13 @@
 #define USB_TOKEN_IN    0x69 /* device -> host */
 #define USB_TOKEN_OUT   0xe1 /* host -> device */
 
-#define USB_RET_NODEV   (-1)
-#define USB_RET_NAK     (-2)
-#define USB_RET_STALL   (-3)
-#define USB_RET_BABBLE  (-4)
-#define USB_RET_IOERROR (-5)
-#define USB_RET_ASYNC   (-6)
+#define USB_RET_NODEV             (-1)
+#define USB_RET_NAK               (-2)
+#define USB_RET_STALL             (-3)
+#define USB_RET_BABBLE            (-4)
+#define USB_RET_IOERROR           (-5)
+#define USB_RET_ASYNC             (-6)
+#define USB_RET_ADD_TO_QUEUE      (-7)
 
 #define USB_SPEED_LOW   0
 #define USB_SPEED_FULL  1
@@ -293,6 +294,12 @@ typedef struct USBDeviceClass {
     void (*set_interface)(USBDevice *dev, int interface,
                           int alt_old, int alt_new);
 
+    /*
+     * Called when the hcd is done queuing packets for an endpoint, only
+     * necessary for devices which can return USB_RET_ADD_TO_QUEUE.
+     */
+    void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep);
+
     const char *product_desc;
     const USBDesc *usb_desc;
 } USBDeviceClass;
@@ -507,6 +514,8 @@ int usb_device_handle_data(USBDevice *dev, USBPacket *p);
 void usb_device_set_interface(USBDevice *dev, int interface,
                               int alt_old, int alt_new);
 
+void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep);
+
 const char *usb_device_get_product_desc(USBDevice *dev);
 
 const USBDesc *usb_device_get_usb_desc(USBDevice *dev);
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index b649360..8066291 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -181,6 +181,14 @@ void usb_device_set_interface(USBDevice *dev, int interface,
     }
 }
 
+void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
+{
+    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
+    if (klass->flush_ep_queue) {
+        klass->flush_ep_queue(dev, ep);
+    }
+}
+
 static int usb_qdev_init(DeviceState *qdev)
 {
     USBDevice *dev = USB_DEVICE(qdev);
diff --git a/hw/usb/core.c b/hw/usb/core.c
index e2e31ca..014e3ac 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -393,6 +393,10 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
         if (ret == USB_RET_ASYNC) {
             usb_packet_set_state(p, USB_PACKET_ASYNC);
             QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+        } else if (ret == USB_RET_ADD_TO_QUEUE) {
+            usb_packet_set_state(p, USB_PACKET_QUEUED);
+            QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+            ret = USB_RET_ASYNC;
         } else {
             /*
              * When pipelining is enabled usb-devices must always return async,
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index a02fe96..d11311e 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2072,6 +2072,7 @@ static int ehci_state_horizqh(EHCIQueue *q)
 
 static int ehci_fill_queue(EHCIPacket *p)
 {
+    USBEndpoint *ep = p->packet.ep;
     EHCIQueue *q = p->queue;
     EHCIqtd qtd = p->qtd;
     uint32_t qtdaddr, start_addr = p->qtdaddr;
@@ -2107,6 +2108,9 @@ static int ehci_fill_queue(EHCIPacket *p)
         assert(p->usb_status == USB_RET_ASYNC);
         p->async = EHCI_ASYNC_INFLIGHT;
     }
+    if (p->usb_status != USB_RET_PROCERR) {
+        usb_device_flush_ep_queue(ep->dev, ep);
+    }
     return p->usb_status;
 }
 
diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c
index dc114fe..212dd12 100644
--- a/hw/usb/hcd-musb.c
+++ b/hw/usb/hcd-musb.c
@@ -635,6 +635,7 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     ret = usb_handle_packet(dev, &ep->packey[dir].p);
 
     if (ret == USB_RET_ASYNC) {
+        usb_device_flush_ep_queue(dev, uep);
         ep->status[dir] = len;
         return;
     }
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 0cc1e5d..31dcfbb 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -816,6 +816,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
         ret = usb_handle_packet(dev, &ohci->usb_packet);
         if (ret == USB_RET_ASYNC) {
+            usb_device_flush_ep_queue(dev, ep);
             return 1;
         }
     }
@@ -1018,6 +1019,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
         DPRINTF("ret=%d\n", ret);
 #endif
         if (ret == USB_RET_ASYNC) {
+            usb_device_flush_ep_queue(dev, ep);
             ohci->async_td = addr;
             return 1;
         }
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 600d095..46e544b 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -818,7 +818,8 @@ out:
 }
 
 static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
-                          uint32_t *int_mask, bool queuing)
+                          uint32_t *int_mask, bool queuing,
+                          struct USBEndpoint **ep_ret)
 {
     UHCIAsync *async;
     int len = 0, max_len;
@@ -870,6 +871,9 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
 
     dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
     ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
+    if (ep_ret) {
+        *ep_ret = ep;
+    }
     usb_packet_setup(&async->packet, pid, ep, addr);
     qemu_sglist_add(&async->sgl, td->buffer, max_len);
     usb_packet_map(&async->packet, &async->sgl);
@@ -983,7 +987,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr)
     return 0;
 }
 
-static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
+static void uhci_fill_queue(UHCIState *s, UHCI_TD *td, struct USBEndpoint *ep)
 {
     uint32_t int_mask = 0;
     uint32_t plink = td->link;
@@ -1005,7 +1009,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
             break;
         }
         trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
-        ret = uhci_handle_td(s, plink, &ptd, &int_mask, true);
+        ret = uhci_handle_td(s, plink, &ptd, &int_mask, true, NULL);
         if (ret == TD_RESULT_ASYNC_CONT) {
             break;
         }
@@ -1013,12 +1017,14 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
         assert(int_mask == 0);
         plink = ptd.link;
     }
+    usb_device_flush_ep_queue(ep->dev, ep);
 }
 
 static void uhci_process_frame(UHCIState *s)
 {
     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
     uint32_t curr_qh, td_count = 0;
+    struct USBEndpoint *curr_ep;
     int cnt, ret;
     UHCI_TD td;
     UHCI_QH qh;
@@ -1089,7 +1095,7 @@ static void uhci_process_frame(UHCIState *s)
         trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token);
 
         old_td_ctrl = td.ctrl;
-        ret = uhci_handle_td(s, link, &td, &int_mask, false);
+        ret = uhci_handle_td(s, link, &td, &int_mask, false, &curr_ep);
         if (old_td_ctrl != td.ctrl) {
             /* update the status bits of the TD */
             val = cpu_to_le32(td.ctrl);
@@ -1108,7 +1114,7 @@ static void uhci_process_frame(UHCIState *s)
 
         case TD_RESULT_ASYNC_START:
             trace_usb_uhci_td_async(curr_qh & ~0xf, link & ~0xf);
-            uhci_fill_queue(s, &td);
+            uhci_fill_queue(s, &td, curr_ep);
             link = curr_qh ? qh.link : td.link;
             continue;
 
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 47d5702..e8929a0 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1652,6 +1652,7 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid)
 {
     XHCIEPContext *epctx;
+    USBEndpoint *ep = NULL;
     uint64_t mfindex;
     int length;
     int i;
@@ -1745,12 +1746,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
         if (epid == 1) {
             if (xhci_fire_ctl_transfer(xhci, xfer) >= 0) {
                 epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
+                ep = xfer->packet.ep;
             } else {
                 fprintf(stderr, "xhci: error firing CTL transfer\n");
             }
         } else {
             if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) {
                 epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
+                ep = xfer->packet.ep;
             } else {
                 if (!xfer->iso_xfer) {
                     fprintf(stderr, "xhci: error firing data transfer\n");
@@ -1767,6 +1770,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
             break;
         }
     }
+    if (ep) {
+        usb_device_flush_ep_queue(ep->dev, ep);
+    }
 }
 
 static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid)
-- 
1.7.1

  parent reply	other threads:[~2012-10-25 12:52 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-25 12:51 [Qemu-devel] [PULL 00/36] usb patch queue Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 01/36] uhci: Properly unmap packets on cancel / invalid pid Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 02/36] uhci: Move checks to continue queuing to uhci_fill_queue() Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 03/36] ehci: Get rid of packet tbytes field Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 04/36] ehci: Set int flag on a short input packet Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 05/36] ehci: Improve latency of interrupt delivery and async schedule scanning Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 06/36] ehci: Speed up the timer of raising int from the async schedule Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 07/36] ehci: Detect going in circles when filling the queue Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 08/36] ehci: Retry to fill the queue while waiting for td completion Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 09/36] xhci: Add a xhci_ep_nuke_one_xfer helper function Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 10/36] usb: Rename __usb_packet_complete to usb_packet_complete_one Gerd Hoffmann
2012-10-25 12:51 ` Gerd Hoffmann [this message]
2012-10-25 12:51 ` [Qemu-devel] [PATCH 12/36] usb: Move clearing of queue on halt to the core Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 13/36] usb: Move short-not-ok handling " Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 14/36] usb: Add an int_req flag to USBPacket Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 15/36] usb: Enforce iso endpoints never returing USB_RET_ASYNC Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 16/36] uhci: No need to handle async completion of isoc packets Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 17/36] uhci: cleanup: Add an unlink call to uhci_async_cancel() Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 18/36] uhci: Don't retry on error Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 19/36] uhci: Drop unnecessary forward declaration of some static functions Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 20/36] uhci: Move emptying of the queue's asyncs' queue to uhci_queue_free Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 21/36] uhci: Rename UHCIAsync->td to UHCIAsync->td_addr Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 22/36] uhci: Add uhci_read_td() helper function Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 23/36] uhci: Make uhci_fill_queue() actually operate on an UHCIQueue Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 24/36] uhci: Store ep in UHCIQueue Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 25/36] uhci: Immediately free queues on device disconnect Gerd Hoffmann
2012-10-25 12:51 ` [Qemu-devel] [PATCH 26/36] uhci: Verify queue has not been changed by guest Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 27/36] uhci: Detect guest td re-use Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 28/36] uhci: When the guest marks a pending td non-active, cancel the queue Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 29/36] uhci: Always mark a queue valid when we encounter it Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 30/36] uhci: Retry to fill the queue while waiting for td completion Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 31/36] uhci: Use only one queue for ctrl endpoints Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 32/36] xhci: fix function name in error message Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 33/36] xhci: flush endpoint context unconditinally Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 34/36] xhci: allow disabling interrupters Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 35/36] xhci: make number of interrupters and slots configurable Gerd Hoffmann
2012-10-25 12:52 ` [Qemu-devel] [PATCH 36/36] xhci: fix usb name in caps Gerd Hoffmann
2012-10-29 19:25 ` [Qemu-devel] [PULL 00/36] 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=1351169529-10799-12-git-send-email-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=hdegoede@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).