diff mbox

[v4,18/32] usb: uhci: remote wakeup support.

Message ID 1294831214-4499-19-git-send-email-kraxel@redhat.com
State New
Headers show

Commit Message

Gerd Hoffmann Jan. 12, 2011, 11:20 a.m. UTC
Add support for remote wakeup to the UHCI adapter.

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

Comments

Stefan Hajnoczi Jan. 12, 2011, 12:25 p.m. UTC | #1
On Wed, Jan 12, 2011 at 11:20 AM, Gerd Hoffmann <kraxel@redhat.com> wrote:
> Add support for remote wakeup to the UHCI adapter.

It would be nice to document the guest configuration steps for users
so they can take advantage of this.  Perhaps on the qemu.org wiki?  Or
http://www.linux-kvm.org/page/Usb_related?

Stefan
Gerd Hoffmann Jan. 14, 2011, 11:56 a.m. UTC | #2
On 01/12/11 13:25, Stefan Hajnoczi wrote:
> On Wed, Jan 12, 2011 at 11:20 AM, Gerd Hoffmann<kraxel@redhat.com>  wrote:
>> Add support for remote wakeup to the UHCI adapter.
>
> It would be nice to document the guest configuration steps for users
> so they can take advantage of this.  Perhaps on the qemu.org wiki?  Or
> http://www.linux-kvm.org/page/Usb_related?

qemu wiki is probably the better place as this isn't kvm-specific.  Will 
do once this is merged.

cheers,
   Gerd
diff mbox

Patch

diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 5e2e34a..2d2a9e7 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -57,13 +57,18 @@ 
 #define TD_CTRL_NAK     (1 << 19)
 #define TD_CTRL_TIMEOUT (1 << 18)
 
+#define UHCI_PORT_SUSPEND (1 << 12)
 #define UHCI_PORT_RESET (1 << 9)
 #define UHCI_PORT_LSDA  (1 << 8)
+#define UHCI_PORT_RD    (1 << 6)
 #define UHCI_PORT_ENC   (1 << 3)
 #define UHCI_PORT_EN    (1 << 2)
 #define UHCI_PORT_CSC   (1 << 1)
 #define UHCI_PORT_CCS   (1 << 0)
 
+#define UHCI_PORT_READ_ONLY    (0x1bb)
+#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)
+
 #define FRAME_TIMER_FREQ 1000
 
 #define FRAME_MAX_LOOPS  100
@@ -497,9 +502,10 @@  static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                     usb_send_msg(dev, USB_MSG_RESET);
                 }
             }
-            port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
+            port->ctrl &= UHCI_PORT_READ_ONLY;
+            port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
             /* some bits are reset when a '1' is written to them */
-            port->ctrl &= ~(val & 0x000a);
+            port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);
         }
         break;
     }
@@ -629,6 +635,18 @@  static void uhci_detach(USBPort *port1)
     uhci_resume(s);
 }
 
+static void uhci_wakeup(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    UHCIState *s = container_of(bus, UHCIState, bus);
+    UHCIPort *port = s->ports + dev->port->index;
+
+    if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
+        port->ctrl |= UHCI_PORT_RD;
+        uhci_resume(s);
+    }
+}
+
 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
 {
     int i, ret;
@@ -1094,6 +1112,7 @@  static void uhci_map(PCIDevice *pci_dev, int region_num,
 static USBPortOps uhci_port_ops = {
     .attach = uhci_attach,
     .detach = uhci_detach,
+    .wakeup = uhci_wakeup,
 };
 
 static int usb_uhci_common_initfn(UHCIState *s)