<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From 7525bc814d80282b86bfece0ea83a1abac1fd5a7 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann &lt;kraxel@redhat.com&gt;
Date: Thu, 23 Jun 2011 12:41:00 -0300
Subject: [RHEL6 qemu-kvm PATCH 027/115] usb: rework attach/detach workflow

RH-Author: Gerd Hoffmann &lt;kraxel@redhat.com&gt;
Message-id: &lt;1308832951-8995-25-git-send-email-kraxel@redhat.com&gt;
Patchwork-id: 27896
O-Subject: [RHEL-6.2 kvm PATCH 024/115] usb: rework attach/detach workflow
Bugzilla: 561414 632299 645351 711354
RH-Acked-by: Hans de Goede &lt;hdegoede@redhat.com&gt;
RH-Acked-by: Jes Sorensen &lt;Jes.Sorensen@redhat.com&gt;
RH-Acked-by: Paolo Bonzini &lt;pbonzini@redhat.com&gt;
RH-Acked-by: Kevin Wolf &lt;kwolf@redhat.com&gt;

Add separate detach callback to USBPortOps, split
uhci/ohci/musb/usbhub attach functions into two.

Move common code to the usb_attach() function, only
the hardware-specific bits remain in the attach/detach
callbacks.

Keep track of the port it is attached to for each usb device.

[ v3: fix tyops in usb-musb.c ]

Signed-off-by: Gerd Hoffmann &lt;kraxel@redhat.com&gt;
(cherry picked from commit 618c169b577db64ac6589ad48825d2e11760d1a6)

Conflicts:

	hw/usb-musb.c
	hw/usb-ohci.c
---
 hw/usb-hub.c  |   46 ++++++++++++++------------------
 hw/usb-musb.c |   36 ++++++++-----------------
 hw/usb-ohci.c |   80 +++++++++++++++++++++++++++------------------------------
 hw/usb-uhci.c |   69 +++++++++++++++++++++---------------------------
 hw/usb.c      |   20 +++++++++++++-
 hw/usb.h      |    4 ++-
 6 files changed, 122 insertions(+), 133 deletions(-)

Signed-off-by: Eduardo Habkost &lt;ehabkost@redhat.com&gt;
---
 hw/usb-hub.c  |   46 ++++++++++++++------------------
 hw/usb-musb.c |   36 ++++++++-----------------
 hw/usb-ohci.c |   80 +++++++++++++++++++++++++++------------------------------
 hw/usb-uhci.c |   69 +++++++++++++++++++++---------------------------
 hw/usb.c      |   20 +++++++++++++-
 hw/usb.h      |    4 ++-
 6 files changed, 122 insertions(+), 133 deletions(-)

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 7c2e184..74b9ceb 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -218,37 +218,30 @@ static const uint8_t qemu_hub_hub_descriptor[] =
         /* DeviceRemovable and PortPwrCtrlMask patched in later */
 };
 
-static void usb_hub_attach(USBPort *port1, USBDevice *dev)
+static void usb_hub_attach(USBPort *port1)
 {
     USBHubState *s = port1-&gt;opaque;
     USBHubPort *port = &amp;s-&gt;ports[port1-&gt;index];
 
-    if (dev) {
-        if (port-&gt;port.dev)
-            usb_attach(port1, NULL);
-
-        port-&gt;wPortStatus |= PORT_STAT_CONNECTION;
-        port-&gt;wPortChange |= PORT_STAT_C_CONNECTION;
-        if (dev-&gt;speed == USB_SPEED_LOW)
-            port-&gt;wPortStatus |= PORT_STAT_LOW_SPEED;
-        else
-            port-&gt;wPortStatus &amp;= ~PORT_STAT_LOW_SPEED;
-        port-&gt;port.dev = dev;
-        /* send the attach message */
-        usb_send_msg(dev, USB_MSG_ATTACH);
+    port-&gt;wPortStatus |= PORT_STAT_CONNECTION;
+    port-&gt;wPortChange |= PORT_STAT_C_CONNECTION;
+    if (port-&gt;port.dev-&gt;speed == USB_SPEED_LOW) {
+        port-&gt;wPortStatus |= PORT_STAT_LOW_SPEED;
     } else {
-        dev = port-&gt;port.dev;
-        if (dev) {
-            port-&gt;wPortStatus &amp;= ~PORT_STAT_CONNECTION;
-            port-&gt;wPortChange |= PORT_STAT_C_CONNECTION;
-            if (port-&gt;wPortStatus &amp; PORT_STAT_ENABLE) {
-                port-&gt;wPortStatus &amp;= ~PORT_STAT_ENABLE;
-                port-&gt;wPortChange |= PORT_STAT_C_ENABLE;
-            }
-            /* send the detach message */
-            usb_send_msg(dev, USB_MSG_DETACH);
-            port-&gt;port.dev = NULL;
-        }
+        port-&gt;wPortStatus &amp;= ~PORT_STAT_LOW_SPEED;
+    }
+}
+
+static void usb_hub_detach(USBPort *port1)
+{
+    USBHubState *s = port1-&gt;opaque;
+    USBHubPort *port = &amp;s-&gt;ports[port1-&gt;index];
+
+    port-&gt;wPortStatus &amp;= ~PORT_STAT_CONNECTION;
+    port-&gt;wPortChange |= PORT_STAT_C_CONNECTION;
+    if (port-&gt;wPortStatus &amp; PORT_STAT_ENABLE) {
+        port-&gt;wPortStatus &amp;= ~PORT_STAT_ENABLE;
+        port-&gt;wPortChange |= PORT_STAT_C_ENABLE;
     }
 }
 
@@ -508,6 +501,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
 
 static USBPortOps usb_hub_port_ops = {
     .attach = usb_hub_attach,
+    .detach = usb_hub_detach,
 };
 
 static int usb_hub_initfn(USBDevice *dev)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index ef592aa..6cf95be 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -248,10 +248,12 @@
 #define MGC_M_ULPI_REGCTL_COMPLETE	0x02
 #define MGC_M_ULPI_REGCTL_REG		0x01
 
-static void musb_attach(USBPort *port, USBDevice *dev);
+static void musb_attach(USBPort *port);
+static void musb_detach(USBPort *port);
 
 static USBPortOps musb_port_ops = {
     .attach = musb_attach,
+    .detach = musb_detach,
 };
 
 typedef struct {
@@ -453,34 +455,20 @@ static void musb_session_update(MUSBState *s, int prev_dev, int prev_sess)
 }
 
 /* Attach or detach a device on our only port.  */
-static void musb_attach(USBPort *port, USBDevice *dev)
+static void musb_attach(USBPort *port)
 {
     MUSBState *s = (MUSBState *) port-&gt;opaque;
-    USBDevice *curr;
 
-    port = &amp;s-&gt;port;
-    curr = port-&gt;dev;
-
-    if (dev) {
-        if (curr) {
-            usb_attach(port, NULL);
-            /* TODO: signal some interrupts */
-        }
-
-        musb_intr_set(s, musb_irq_vbus_request, 1);
-
-        /* Send the attach message to device */
-        usb_send_msg(dev, USB_MSG_ATTACH);
-    } else if (curr) {
-        /* Send the detach message */
-        usb_send_msg(curr, USB_MSG_DETACH);
-
-        musb_intr_set(s, musb_irq_disconnect, 1);
-    }
+    musb_intr_set(s, musb_irq_vbus_request, 1);
+    musb_session_update(s, 0, s-&gt;session);
+}
 
-    port-&gt;dev = dev;
+static void musb_detach(USBPort *port)
+{
+    MUSBState *s = (MUSBState *) port-&gt;opaque;
 
-    musb_session_update(s, !!curr, s-&gt;session);
+    musb_intr_set(s, musb_irq_disconnect, 1);
+    musb_session_update(s, 1, s-&gt;session);
 }
 
 static inline void musb_cb_tick0(void *opaque)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index cb6369f..bc9463a 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -329,52 +329,46 @@ static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
 }
 
 /* Attach or detach a device on a root hub port.  */
-static void ohci_attach(USBPort *port1, USBDevice *dev)
+static void ohci_attach(USBPort *port1)
 {
     OHCIState *s = port1-&gt;opaque;
     OHCIPort *port = &amp;s-&gt;rhport[port1-&gt;index];
-    uint32_t old_state = port-&gt;ctrl;
 
-    if (dev) {
-        if (port-&gt;port.dev) {
-            usb_attach(port1, NULL);
-        }
-        /* set connect status */
-        port-&gt;ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
-
-        /* update speed */
-        if (dev-&gt;speed == USB_SPEED_LOW)
-            port-&gt;ctrl |= OHCI_PORT_LSDA;
-        else
-            port-&gt;ctrl &amp;= ~OHCI_PORT_LSDA;
-        port-&gt;port.dev = dev;
-
-        /* notify of remote-wakeup */
-        if ((s-&gt;ctl &amp; OHCI_CTL_HCFS) == OHCI_USB_SUSPEND)
-            ohci_set_interrupt(s, OHCI_INTR_RD);
-
-        /* send the attach message */
-        usb_send_msg(dev, USB_MSG_ATTACH);
-        dprintf("usb-ohci: Attached port %d\n", port1-&gt;index);
+    /* set connect status */
+    port-&gt;ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
+
+    /* update speed */
+    if (port-&gt;port.dev-&gt;speed == USB_SPEED_LOW) {
+        port-&gt;ctrl |= OHCI_PORT_LSDA;
     } else {
-        /* set connect status */
-        if (port-&gt;ctrl &amp; OHCI_PORT_CCS) {
-            port-&gt;ctrl &amp;= ~OHCI_PORT_CCS;
-            port-&gt;ctrl |= OHCI_PORT_CSC;
-        }
-        /* disable port */
-        if (port-&gt;ctrl &amp; OHCI_PORT_PES) {
-            port-&gt;ctrl &amp;= ~OHCI_PORT_PES;
-            port-&gt;ctrl |= OHCI_PORT_PESC;
-        }
-        dev = port-&gt;port.dev;
-        if (dev) {
-            /* send the detach message */
-            usb_send_msg(dev, USB_MSG_DETACH);
-        }
-        port-&gt;port.dev = NULL;
-        dprintf("usb-ohci: Detached port %d\n", port1-&gt;index);
+        port-&gt;ctrl &amp;= ~OHCI_PORT_LSDA;
+    }
+
+    /* notify of remote-wakeup */
+    if ((s-&gt;ctl &amp; OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+        ohci_set_interrupt(s, OHCI_INTR_RD);
+    }
+
+    DPRINTF("usb-ohci: Attached port %d\n", port1-&gt;index);
+}
+
+static void ohci_detach(USBPort *port1)
+{
+    OHCIState *s = port1-&gt;opaque;
+    OHCIPort *port = &amp;s-&gt;rhport[port1-&gt;index];
+    uint32_t old_state = port-&gt;ctrl;
+
+    /* set connect status */
+    if (port-&gt;ctrl &amp; OHCI_PORT_CCS) {
+        port-&gt;ctrl &amp;= ~OHCI_PORT_CCS;
+        port-&gt;ctrl |= OHCI_PORT_CSC;
+    }
+    /* disable port */
+    if (port-&gt;ctrl &amp; OHCI_PORT_PES) {
+        port-&gt;ctrl &amp;= ~OHCI_PORT_PES;
+        port-&gt;ctrl |= OHCI_PORT_PESC;
     }
+    DPRINTF("usb-ohci: Detached port %d\n", port1-&gt;index);
 
     if (old_state != port-&gt;ctrl)
         ohci_set_interrupt(s, OHCI_INTR_RHSC);
@@ -420,8 +414,9 @@ static void ohci_reset(void *opaque)
       {
         port = &amp;ohci-&gt;rhport[i];
         port-&gt;ctrl = 0;
-        if (port-&gt;port.dev)
-            ohci_attach(&amp;port-&gt;port, port-&gt;port.dev);
+        if (port-&gt;port.dev) {
+            usb_attach(&amp;port-&gt;port, port-&gt;port.dev);
+        }
       }
     if (ohci-&gt;async_td) {
         usb_cancel_packet(&amp;ohci-&gt;usb_packet);
@@ -1663,6 +1658,7 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
 
 static USBPortOps ohci_port_ops = {
     .attach = ohci_attach,
+    .detach = ohci_detach,
 };
 
 static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index a64c458..0751134 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -304,8 +304,6 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token
     return match;
 }
 
-static void uhci_attach(USBPort *port1, USBDevice *dev);
-
 static void uhci_update_irq(UHCIState *s)
 {
     int level;
@@ -345,8 +343,9 @@ static void uhci_reset(void *opaque)
     for(i = 0; i &lt; NB_PORTS; i++) {
         port = &amp;s-&gt;ports[i];
         port-&gt;ctrl = 0x0080;
-        if (port-&gt;port.dev)
-            uhci_attach(&amp;port-&gt;port, port-&gt;port.dev);
+        if (port-&gt;port.dev) {
+            usb_attach(&amp;port-&gt;port, port-&gt;port.dev);
+        }
     }
 
     uhci_async_cancel_all(s);
@@ -589,50 +588,41 @@ static void uhci_resume (void *opaque)
     }
 }
 
-static void uhci_attach(USBPort *port1, USBDevice *dev)
+static void uhci_attach(USBPort *port1)
 {
     UHCIState *s = port1-&gt;opaque;
     UHCIPort *port = &amp;s-&gt;ports[port1-&gt;index];
 
-    if (dev) {
-        if (port-&gt;port.dev) {
-            usb_attach(port1, NULL);
-        }
-        /* set connect status */
-        port-&gt;ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+    /* set connect status */
+    port-&gt;ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
 
-        /* update speed */
-        if (dev-&gt;speed == USB_SPEED_LOW)
-            port-&gt;ctrl |= UHCI_PORT_LSDA;
-        else
-            port-&gt;ctrl &amp;= ~UHCI_PORT_LSDA;
-
-        uhci_resume(s);
-
-        port-&gt;port.dev = dev;
-        /* send the attach message */
-        usb_send_msg(dev, USB_MSG_ATTACH);
+    /* update speed */
+    if (port-&gt;port.dev-&gt;speed == USB_SPEED_LOW) {
+        port-&gt;ctrl |= UHCI_PORT_LSDA;
     } else {
-        /* set connect status */
-        if (port-&gt;ctrl &amp; UHCI_PORT_CCS) {
-            port-&gt;ctrl &amp;= ~UHCI_PORT_CCS;
-            port-&gt;ctrl |= UHCI_PORT_CSC;
-        }
-        /* disable port */
-        if (port-&gt;ctrl &amp; UHCI_PORT_EN) {
-            port-&gt;ctrl &amp;= ~UHCI_PORT_EN;
-            port-&gt;ctrl |= UHCI_PORT_ENC;
-        }
+        port-&gt;ctrl &amp;= ~UHCI_PORT_LSDA;
+    }
 
-        uhci_resume(s);
+    uhci_resume(s);
+}
 
-        dev = port-&gt;port.dev;
-        if (dev) {
-            /* send the detach message */
-            usb_send_msg(dev, USB_MSG_DETACH);
-        }
-        port-&gt;port.dev = NULL;
+static void uhci_detach(USBPort *port1)
+{
+    UHCIState *s = port1-&gt;opaque;
+    UHCIPort *port = &amp;s-&gt;ports[port1-&gt;index];
+
+    /* set connect status */
+    if (port-&gt;ctrl &amp; UHCI_PORT_CCS) {
+        port-&gt;ctrl &amp;= ~UHCI_PORT_CCS;
+        port-&gt;ctrl |= UHCI_PORT_CSC;
     }
+    /* disable port */
+    if (port-&gt;ctrl &amp; UHCI_PORT_EN) {
+        port-&gt;ctrl &amp;= ~UHCI_PORT_EN;
+        port-&gt;ctrl |= UHCI_PORT_ENC;
+    }
+
+    uhci_resume(s);
 }
 
 static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
@@ -1063,6 +1053,7 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
 
 static USBPortOps uhci_port_ops = {
     .attach = uhci_attach,
+    .detach = uhci_detach,
 };
 
 static int usb_uhci_common_initfn(UHCIState *s)
diff --git a/hw/usb.c b/hw/usb.c
index 39d29f3..2eda86a 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -28,7 +28,25 @@
 
 void usb_attach(USBPort *port, USBDevice *dev)
 {
-    port-&gt;ops-&gt;attach(port, dev);
+    if (dev != NULL) {
+        /* attach */
+        if (port-&gt;dev) {
+            usb_attach(port, NULL);
+        }
+        dev-&gt;port = port;
+        port-&gt;dev = dev;
+        port-&gt;ops-&gt;attach(port);
+        usb_send_msg(dev, USB_MSG_ATTACH);
+    } else {
+        /* detach */
+        dev = port-&gt;dev;
+        port-&gt;ops-&gt;detach(port);
+        if (dev) {
+            usb_send_msg(dev, USB_MSG_DETACH);
+            dev-&gt;port = NULL;
+            port-&gt;dev = NULL;
+        }
+    }
 }
 
 /**********************/
diff --git a/hw/usb.h b/hw/usb.h
index 7e441f2..4363dc8 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -143,6 +143,7 @@ struct USBDescString {
 struct USBDevice {
     DeviceState qdev;
     USBDeviceInfo *info;
+    USBPort *port;
     void *opaque;
 
     int speed;
@@ -213,7 +214,8 @@ struct USBDeviceInfo {
 };
 
 typedef struct USBPortOps {
-    void (*attach)(USBPort *port, USBDevice *dev);
+    void (*attach)(USBPort *port);
+    void (*detach)(USBPort *port);
 } USBPortOps;
 
 /* USB port on which a device can be connected */
-- 
1.7.3.2

</pre></body></html>