qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL] usb patch queue
@ 2011-10-13 11:08 Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 1/9] usb-storage: fix NULL pointer dereference Gerd Hoffmann
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Here comes the usb patch queue with a bunch of bug fixes.
Check the individual patches for details.

please pull,
  Gerd

The following changes since commit ebffe2afceb1a17b5d134b5debf553955fe5ea1a:

  Merge remote-tracking branch 'qmp/queue/qmp' into staging (2011-10-10 08:21:46 -0500)

are available in the git repository at:

  git://git.kraxel.org/qemu usb.28

Gerd Hoffmann (7):
      usb-storage: fix NULL pointer dereference.
      usb-hub: need to check dev->attached
      usb: fix port reset
      usb-host: factor out code
      usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY
      usb-hid: activate usb tablet / mouse after migration.
      usb-hub: don't trigger assert on packet completion.

Peter Maydell (2):
      hw/usb-ohci: Fix OHCI_TD_T1 bit position definition
      hw/usb-ohci: Honour endpoint maximum packet size

 hw/usb-ehci.c |    4 +-
 hw/usb-hid.c  |   11 ++++
 hw/usb-hub.c  |   12 +++-
 hw/usb-msd.c  |    5 +-
 hw/usb-ohci.c |   41 +++++++++----
 hw/usb-uhci.c |    2 +-
 hw/usb.c      |   12 ++++
 hw/usb.h      |    1 +
 usb-linux.c   |  176 ++++++++++++++++++++++++++++++++++++---------------------
 9 files changed, 180 insertions(+), 84 deletions(-)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 1/9] usb-storage: fix NULL pointer dereference.
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
@ 2011-10-13 11:08 ` Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 2/9] usb-hub: need to check dev->attached Gerd Hoffmann
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

When a usb packet is canceled we need to check whenever we actually have
a scsi request in flight before we try to cancel it.

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

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index e92434c..08d2d2a 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -325,7 +325,10 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
 static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
-    scsi_req_cancel(s->req);
+
+    if (s->req) {
+        scsi_req_cancel(s->req);
+    }
 }
 
 static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 2/9] usb-hub: need to check dev->attached
  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 ` Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 3/9] usb: fix port reset Gerd Hoffmann
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

commit 891fb2cd4592b6fe76106a69e0ca40efbf82726a did that for all host
controllers, the usb hub was left out by accident.

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

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 286e3ad..39382c7 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -289,7 +289,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                 port->wPortStatus |= PORT_STAT_SUSPEND;
                 break;
             case PORT_RESET:
-                if (dev) {
+                if (dev && dev->attached) {
                     usb_send_msg(dev, USB_MSG_RESET);
                     port->wPortChange |= PORT_STAT_C_RESET;
                     /* set enable bit */
@@ -429,7 +429,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
     for(i = 0; i < NUM_PORTS; i++) {
         port = &s->ports[i];
         dev = port->port.dev;
-        if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
+        if (dev && dev->attached && (port->wPortStatus & PORT_STAT_ENABLE)) {
             ret = usb_handle_packet(dev, p);
             if (ret != USB_RET_NODEV) {
                 return ret;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 3/9] usb: fix port reset
  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 ` Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 4/9] usb-host: factor out code Gerd Hoffmann
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

commit 891fb2cd4592b6fe76106a69e0ca40efbf82726a removed the implicit
detach before (re-)attaching in usb_attach().  Some usb host controllers
used that behavior though to do a port reset by a detach+attach
sequence.

This patch establishes old behavior by adding a new usb_reset() function
for port resets and putting it into use, thereby also unifying port
reset behavior of all host controllers.  The patch also adds asserts to
usb_attach() and usb_detach() to make sure the calls are symmetrical.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-ehci.c |    4 ++--
 hw/usb-ohci.c |    2 +-
 hw/usb-uhci.c |    2 +-
 hw/usb.c      |   12 ++++++++++++
 hw/usb.h      |    1 +
 5 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 27376a2..bd374c1 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -880,6 +880,7 @@ static void ehci_reset(void *opaque)
         }
         if (devs[i] && devs[i]->attached) {
             usb_attach(&s->ports[i]);
+            usb_send_msg(devs[i], USB_MSG_RESET);
         }
     }
     ehci_queues_rip_all(s);
@@ -978,8 +979,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val)
     if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) {
         trace_usb_ehci_port_reset(port, 0);
         if (dev && dev->attached) {
-            usb_attach(&s->ports[port]);
-            usb_send_msg(dev, USB_MSG_RESET);
+            usb_reset(&s->ports[port]);
             *portsc &= ~PORTSC_CSC;
         }
 
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c3be65a..5e10e21 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -449,7 +449,7 @@ static void ohci_reset(void *opaque)
         port = &ohci->rhport[i];
         port->ctrl = 0;
         if (port->port.dev && port->port.dev->attached) {
-            usb_attach(&port->port);
+            usb_reset(&port->port);
         }
       }
     if (ohci->async_td) {
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 17992cf..171d787 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -341,7 +341,7 @@ static void uhci_reset(void *opaque)
         port = &s->ports[i];
         port->ctrl = 0x0080;
         if (port->port.dev && port->port.dev->attached) {
-            usb_attach(&port->port);
+            usb_reset(&port->port);
         }
     }
 
diff --git a/hw/usb.c b/hw/usb.c
index fa90204..2216efe 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -33,6 +33,7 @@ void usb_attach(USBPort *port)
 
     assert(dev != NULL);
     assert(dev->attached);
+    assert(dev->state == USB_STATE_NOTATTACHED);
     port->ops->attach(port);
     usb_send_msg(dev, USB_MSG_ATTACH);
 }
@@ -42,10 +43,21 @@ void usb_detach(USBPort *port)
     USBDevice *dev = port->dev;
 
     assert(dev != NULL);
+    assert(dev->state != USB_STATE_NOTATTACHED);
     port->ops->detach(port);
     usb_send_msg(dev, USB_MSG_DETACH);
 }
 
+void usb_reset(USBPort *port)
+{
+    USBDevice *dev = port->dev;
+
+    assert(dev != NULL);
+    usb_detach(port);
+    usb_attach(port);
+    usb_send_msg(dev, USB_MSG_RESET);
+}
+
 void usb_wakeup(USBDevice *dev)
 {
     if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
diff --git a/hw/usb.h b/hw/usb.h
index c08d469..c6e1870 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -306,6 +306,7 @@ void usb_cancel_packet(USBPacket * p);
 
 void usb_attach(USBPort *port);
 void usb_detach(USBPort *port);
+void usb_reset(USBPort *port);
 void usb_wakeup(USBDevice *dev);
 int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
 void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 4/9] usb-host: factor out code
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 3/9] usb: fix port reset Gerd Hoffmann
@ 2011-10-13 11:08 ` Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 5/9] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY Gerd Hoffmann
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Move code to claim usb ports and to disconnect usb interfaces into
usb_host_claim_port and usb_host_disconnect_ifaces functions.  No
functional change.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 usb-linux.c |  140 ++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 77 insertions(+), 63 deletions(-)

diff --git a/usb-linux.c b/usb-linux.c
index 2075c4c..ff1a29c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -411,6 +411,80 @@ static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
     }
 }
 
+static int usb_host_claim_port(USBHostDevice *s)
+{
+#ifdef USBDEVFS_CLAIM_PORT
+    char *h, hub_name[64], line[1024];
+    int hub_addr, portnr, ret;
+
+    snprintf(hub_name, sizeof(hub_name), "%d-%s",
+             s->match.bus_num, s->match.port);
+
+    /* try strip off last ".$portnr" to get hub */
+    h = strrchr(hub_name, '.');
+    if (h != NULL) {
+        portnr = atoi(h+1);
+        *h = '\0';
+    } else {
+        /* no dot in there -> it is the root hub */
+        snprintf(hub_name, sizeof(hub_name), "usb%d",
+                 s->match.bus_num);
+        portnr = atoi(s->match.port);
+    }
+
+    if (!usb_host_read_file(line, sizeof(line), "devnum",
+                            hub_name)) {
+        return -1;
+    }
+    if (sscanf(line, "%d", &hub_addr) != 1) {
+        return -1;
+    }
+
+    if (!usb_host_device_path) {
+        return -1;
+    }
+    snprintf(line, sizeof(line), "%s/%03d/%03d",
+             usb_host_device_path, s->match.bus_num, hub_addr);
+    s->hub_fd = open(line, O_RDWR | O_NONBLOCK);
+    if (s->hub_fd < 0) {
+        return -1;
+    }
+
+    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
+    if (ret < 0) {
+        close(s->hub_fd);
+        s->hub_fd = -1;
+        return -1;
+    }
+
+    trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
+    return 0;
+#else
+    return -1;
+#endif
+}
+
+static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
+{
+    /* earlier Linux 2.4 do not support that */
+#ifdef USBDEVFS_DISCONNECT
+    struct usbdevfs_ioctl ctrl;
+    int ret, interface;
+
+    for (interface = 0; interface < nb_interfaces; interface++) {
+        ctrl.ioctl_code = USBDEVFS_DISCONNECT;
+        ctrl.ifno = interface;
+        ctrl.data = 0;
+        ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
+        if (ret < 0 && errno != ENODATA) {
+            perror("USBDEVFS_DISCONNECT");
+            return -1;
+        }
+    }
+#endif
+    return 0;
+}
+
 static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
 {
     const char *op = NULL;
@@ -462,22 +536,9 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
     }
     nb_interfaces = dev->descr[i + 4];
 
-#ifdef USBDEVFS_DISCONNECT
-    /* earlier Linux 2.4 do not support that */
-    {
-        struct usbdevfs_ioctl ctrl;
-        for (interface = 0; interface < nb_interfaces; interface++) {
-            ctrl.ioctl_code = USBDEVFS_DISCONNECT;
-            ctrl.ifno = interface;
-            ctrl.data = 0;
-            op = "USBDEVFS_DISCONNECT";
-            ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
-            if (ret < 0 && errno != ENODATA) {
-                goto fail;
-            }
-        }
+    if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) {
+        goto fail;
     }
-#endif
 
     /* XXX: only grab if all interfaces are free */
     for (interface = 0; interface < nb_interfaces; interface++) {
@@ -1301,56 +1362,9 @@ static int usb_host_initfn(USBDevice *dev)
     qemu_add_exit_notifier(&s->exit);
     usb_host_auto_check(NULL);
 
-#ifdef USBDEVFS_CLAIM_PORT
     if (s->match.bus_num != 0 && s->match.port != NULL) {
-        char *h, hub_name[64], line[1024];
-        int hub_addr, portnr, ret;
-
-        snprintf(hub_name, sizeof(hub_name), "%d-%s",
-                 s->match.bus_num, s->match.port);
-
-        /* try strip off last ".$portnr" to get hub */
-        h = strrchr(hub_name, '.');
-        if (h != NULL) {
-            portnr = atoi(h+1);
-            *h = '\0';
-        } else {
-            /* no dot in there -> it is the root hub */
-            snprintf(hub_name, sizeof(hub_name), "usb%d",
-                     s->match.bus_num);
-            portnr = atoi(s->match.port);
-        }
-
-        if (!usb_host_read_file(line, sizeof(line), "devnum",
-                                hub_name)) {
-            goto out;
-        }
-        if (sscanf(line, "%d", &hub_addr) != 1) {
-            goto out;
-        }
-
-        if (!usb_host_device_path) {
-            goto out;
-        }
-        snprintf(line, sizeof(line), "%s/%03d/%03d",
-                 usb_host_device_path, s->match.bus_num, hub_addr);
-        s->hub_fd = open(line, O_RDWR | O_NONBLOCK);
-        if (s->hub_fd < 0) {
-            goto out;
-        }
-
-        ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
-        if (ret < 0) {
-            close(s->hub_fd);
-            s->hub_fd = -1;
-            goto out;
-        }
-
-        trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
+        usb_host_claim_port(s);
     }
-out:
-#endif
-
     return 0;
 }
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 5/9] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 4/9] usb-host: factor out code Gerd Hoffmann
@ 2011-10-13 11:08 ` Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 6/9] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition Gerd Hoffmann
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

In case the host uses the usb device usbfs will refuse to set the
configuration due to the device being busy.  Handle this case by
disconnection the interfaces, then trying again.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 usb-linux.c |   36 +++++++++++++++++++++++++++++++++++-
 1 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/usb-linux.c b/usb-linux.c
index ff1a29c..7d4d1d7 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -485,6 +485,26 @@ static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
     return 0;
 }
 
+static int usb_linux_get_num_interfaces(USBHostDevice *s)
+{
+    char device_name[64], line[1024];
+    int num_interfaces = 0;
+
+    if (usb_fs_type != USB_FS_SYS) {
+        return -1;
+    }
+
+    sprintf(device_name, "%d-%s", s->bus_num, s->port);
+    if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces",
+                            device_name)) {
+        return -1;
+    }
+    if (sscanf(line, "%d", &num_interfaces) != 1) {
+        return -1;
+    }
+    return num_interfaces;
+}
+
 static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
 {
     const char *op = NULL;
@@ -901,14 +921,28 @@ static int usb_host_set_address(USBHostDevice *s, int addr)
 
 static int usb_host_set_config(USBHostDevice *s, int config)
 {
+    int ret, first = 1;
+
     trace_usb_host_set_config(s->bus_num, s->addr, config);
 
     usb_host_release_interfaces(s);
 
-    int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
+again:
+    ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
 
     DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
 
+    if (ret < 0 && errno == EBUSY && first) {
+        /* happens if usb device is in use by host drivers */
+        int count = usb_linux_get_num_interfaces(s);
+        if (count > 0) {
+            DPRINTF("husb: busy -> disconnecting %d interfaces\n", count);
+            usb_host_disconnect_ifaces(s, count);
+            first = 0;
+            goto again;
+        }
+    }
+
     if (ret < 0) {
         return ctrl_error();
     }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 6/9] hw/usb-ohci: Fix OHCI_TD_T1 bit position definition
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 5/9] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY Gerd Hoffmann
@ 2011-10-13 11:08 ` Gerd Hoffmann
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 7/9] hw/usb-ohci: Honour endpoint maximum packet size Gerd Hoffmann
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Gerd Hoffmann

From: Peter Maydell <peter.maydell@linaro.org>

The OHCI Transfer Descriptor T (DataToggle) bits are 24 and 25;
fix an error which accidentally overlaid them both on the same bit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-ohci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 5e10e21..e14ced8 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -150,7 +150,7 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
 #define OHCI_TD_DI_SHIFT  21
 #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
 #define OHCI_TD_T0        (1<<24)
-#define OHCI_TD_T1        (1<<24)
+#define OHCI_TD_T1        (1<<25)
 #define OHCI_TD_EC_SHIFT  26
 #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
 #define OHCI_TD_CC_SHIFT  28
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 7/9] hw/usb-ohci: Honour endpoint maximum packet size
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (5 preceding siblings ...)
  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
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 8/9] usb-hid: activate usb tablet / mouse after migration Gerd Hoffmann
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Gerd Hoffmann

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

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 8/9] usb-hid: activate usb tablet / mouse after migration.
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 7/9] hw/usb-ohci: Honour endpoint maximum packet size Gerd Hoffmann
@ 2011-10-13 11:08 ` 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-14 16:25 ` [Qemu-devel] [PULL] usb patch queue Anthony Liguori
  9 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

qemu uses the ps/2 mouse by default.  The usb tablet (or mouse) is
activated as soon as qemu sees some guest activity on the device,
i.e. polling for HID events.  That used to work fine for both fresh
boot and migration.

Remote wakeup support changed the picture though: There will be no
polling after migration in case the guest suspended the usb bus,
waiting for wakeup events.  Result is that the ps/2 mouse stays
active.

Fix this by activating the usb tablet / mouse in post_load() in case
the guest enabled remote wakeup.

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

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index ba79466..a110c74 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -527,10 +527,21 @@ static int usb_keyboard_initfn(USBDevice *dev)
     return usb_hid_initfn(dev, HID_KEYBOARD);
 }
 
+static int usb_ptr_post_load(void *opaque, int version_id)
+{
+    USBHIDState *s = opaque;
+
+    if (s->dev.remote_wakeup) {
+        hid_pointer_activate(&s->hid);
+    }
+    return 0;
+}
+
 static const VMStateDescription vmstate_usb_ptr = {
     .name = "usb-ptr",
     .version_id = 1,
     .minimum_version_id = 1,
+    .post_load = usb_ptr_post_load,
     .fields = (VMStateField []) {
         VMSTATE_USB_DEVICE(dev, USBHIDState),
         VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 9/9] usb-hub: don't trigger assert on packet completion.
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (7 preceding siblings ...)
  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 ` Gerd Hoffmann
  2011-10-13 11:34   ` Gerd Hoffmann
  2011-10-14 16:25 ` [Qemu-devel] [PULL] usb patch queue Anthony Liguori
  9 siblings, 1 reply; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Calling usb_packet_complete() recursively when passing up the completion
event up the chain for devices connected via usb hub will trigger an
assert.  So don't do that, make the usb hub emulation call the upstream
completion callback directly instead.

Based on a patch from Stefan Hajnoczi <stefanha@gmail.com>

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hub.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 39382c7..dab8f51 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -207,10 +207,14 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
     /*
      * Just pass it along upstream for now.
      *
-     * If we ever inplement usb 2.0 split transactions this will
+     * If we ever implement usb 2.0 split transactions this will
      * become a little more complicated ...
+     *
+     * Can't use usb_packet_complete() here because packet->owner is
+     * cleared already, go call the ->complete() callback directly
+     * instead.
      */
-    usb_packet_complete(&s->dev, packet);
+    s->dev.port->ops->complete(&s->dev.port, packet);
 }
 
 static void usb_hub_handle_reset(USBDevice *dev)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 9/9] usb-hub: don't trigger assert on packet completion.
  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
  0 siblings, 0 replies; 12+ messages in thread
From: Gerd Hoffmann @ 2011-10-13 11:34 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 312 bytes --]

   Hi,

> -    usb_packet_complete(&s->dev, packet);
> +    s->dev.port->ops->complete(&s->dev.port, packet);

Oops, that doesn't compile.  Got sidetracked wile waiting for the test 
build finish, then forgot to check the results :(

Updated patch attached.  Branch for pulling updated inplace.

cheers,
   Gerd

[-- Attachment #2: 0001-usb-hub-don-t-trigger-assert-on-packet-completion.patch --]
[-- Type: text/plain, Size: 1433 bytes --]

From 80cf7cf74f29a219e02b50f27c12b1c792ebf99b Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 13 Oct 2011 12:52:47 +0200
Subject: [PATCH] usb-hub: don't trigger assert on packet completion.

Calling usb_packet_complete() recursively when passing up the completion
event up the chain for devices connected via usb hub will trigger an
assert.  So don't do that, make the usb hub emulation call the upstream
completion callback directly instead.

Based on a patch from Stefan Hajnoczi <stefanha@gmail.com>

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb-hub.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 39382c7..09c6516 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -207,10 +207,14 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
     /*
      * Just pass it along upstream for now.
      *
-     * If we ever inplement usb 2.0 split transactions this will
+     * If we ever implement usb 2.0 split transactions this will
      * become a little more complicated ...
+     *
+     * Can't use usb_packet_complete() here because packet->owner is
+     * cleared already, go call the ->complete() callback directly
+     * instead.
      */
-    usb_packet_complete(&s->dev, packet);
+    s->dev.port->ops->complete(s->dev.port, packet);
 }
 
 static void usb_hub_handle_reset(USBDevice *dev)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PULL] usb patch queue
  2011-10-13 11:08 [Qemu-devel] [PULL] usb patch queue Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2011-10-13 11:08 ` [Qemu-devel] [PATCH 9/9] usb-hub: don't trigger assert on packet completion Gerd Hoffmann
@ 2011-10-14 16:25 ` Anthony Liguori
  9 siblings, 0 replies; 12+ messages in thread
From: Anthony Liguori @ 2011-10-14 16:25 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On 10/13/2011 06:08 AM, Gerd Hoffmann wrote:
>    Hi,
>
> Here comes the usb patch queue with a bunch of bug fixes.
> Check the individual patches for details.
>
> please pull,
>    Gerd

Pulled.  Thanks.

Regards,

Anthony Liguori

>
> The following changes since commit ebffe2afceb1a17b5d134b5debf553955fe5ea1a:
>
>    Merge remote-tracking branch 'qmp/queue/qmp' into staging (2011-10-10 08:21:46 -0500)
>
> are available in the git repository at:
>
>    git://git.kraxel.org/qemu usb.28
>
> Gerd Hoffmann (7):
>        usb-storage: fix NULL pointer dereference.
>        usb-hub: need to check dev->attached
>        usb: fix port reset
>        usb-host: factor out code
>        usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY
>        usb-hid: activate usb tablet / mouse after migration.
>        usb-hub: don't trigger assert on packet completion.
>
> Peter Maydell (2):
>        hw/usb-ohci: Fix OHCI_TD_T1 bit position definition
>        hw/usb-ohci: Honour endpoint maximum packet size
>
>   hw/usb-ehci.c |    4 +-
>   hw/usb-hid.c  |   11 ++++
>   hw/usb-hub.c  |   12 +++-
>   hw/usb-msd.c  |    5 +-
>   hw/usb-ohci.c |   41 +++++++++----
>   hw/usb-uhci.c |    2 +-
>   hw/usb.c      |   12 ++++
>   hw/usb.h      |    1 +
>   usb-linux.c   |  176 ++++++++++++++++++++++++++++++++++++---------------------
>   9 files changed, 180 insertions(+), 84 deletions(-)
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2011-10-14 16:25 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [Qemu-devel] [PATCH 7/9] hw/usb-ohci: Honour endpoint maximum packet size Gerd Hoffmann
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

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).