qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 01/28] usb-uhci: implement bandwidth management
Date: Fri, 10 Feb 2012 12:42:57 +0100	[thread overview]
Message-ID: <1328874204-20920-2-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1328874204-20920-1-git-send-email-kraxel@redhat.com>

The OS is allowed to make the UHCI Controller run in circles.  That is
usually done to serve multiple connected USB devices in a robin-round
fashion, so the available USB bandwidth is evenly distributed between
devices.

The uhci emulation handles this in a very poor way though.  When it
figures it runs in circles it stops processing unconditionally, so
it usually processes at most a single transfer desriptor per queue,
even if there are multiple transfer descriptors are queued up.

This patch makes uhci act in a more sophisticated way.  It keeps track
of successful processed transfer descriptors and transfered bytes.  Then
it will stop processing when there is nothing to do (no transfer
descriptor was completed the last round) or when the transfered data
reaches the usb bandwidth limit.

Result is that the usb-storage devices connected to uhci are ten times
faster, mkfs.vfat time for a 64M stick goes down from five seconds to
a half second.  Reason for this is that we are now processing up to 20
transfer descriptors (with 64 bytes each) per frame instead of a single
one.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-uhci.c |   29 ++++++++++++++++++++++-------
 1 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index cddcc89..e0c7dbb 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -73,7 +73,7 @@
 
 #define FRAME_TIMER_FREQ 1000
 
-#define FRAME_MAX_LOOPS  100
+#define FRAME_MAX_LOOPS  256
 
 #define NB_PORTS 2
 
@@ -942,7 +942,7 @@ static int qhdb_insert(QhDb *db, uint32_t addr)
 static void uhci_process_frame(UHCIState *s)
 {
     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
-    uint32_t curr_qh;
+    uint32_t curr_qh, td_count = 0, bytes_count = 0;
     int cnt, ret;
     UHCI_TD td;
     UHCI_QH qh;
@@ -967,13 +967,26 @@ static void uhci_process_frame(UHCIState *s)
             if (qhdb_insert(&qhdb, link)) {
                 /*
                  * We're going in circles. Which is not a bug because
-                 * HCD is allowed to do that as part of the BW management. 
-                 * In our case though it makes no sense to spin here. Sync transations 
-                 * are already done, and async completion handler will re-process 
-                 * the frame when something is ready.
+                 * HCD is allowed to do that as part of the BW management.
+                 *
+                 * Stop processing here if
+                 *  (a) no transaction has been done since we've been
+                 *      here last time, or
+                 *  (b) we've reached the usb 1.1 bandwidth, which is
+                 *      1280 bytes/frame.
                  */
                 DPRINTF("uhci: detected loop. qh 0x%x\n", link);
-                break;
+                if (td_count == 0) {
+                    DPRINTF("uhci: no transaction last round, stop\n");
+                    break;
+                } else if (bytes_count >= 1280) {
+                    DPRINTF("uhci: bandwidth limit reached, stop\n");
+                    break;
+                } else {
+                    td_count = 0;
+                    qhdb_reset(&qhdb);
+                    qhdb_insert(&qhdb, link);
+                }
             }
 
             pci_dma_read(&s->dev, link & ~0xf, &qh, sizeof(qh));
@@ -1033,6 +1046,8 @@ static void uhci_process_frame(UHCIState *s)
                 link, td.link, td.ctrl, td.token, curr_qh);
 
         link = td.link;
+        td_count++;
+        bytes_count += (td.ctrl & 0x7ff) + 1;
 
         if (curr_qh) {
 	    /* update QH element link */
-- 
1.7.1

  reply	other threads:[~2012-02-10 11:43 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 ` Gerd Hoffmann [this message]
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 ` [Qemu-devel] [PATCH 28/28] xhci: handle USB_RET_NAK Gerd Hoffmann
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-2-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).