aboutsummaryrefslogtreecommitdiff
path: root/hw/usb-musb.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-06-24 12:31:11 +0200
committerGerd Hoffmann <kraxel@redhat.com>2011-07-05 15:09:02 +0200
commit4706ab6cc0af86d3f38806664420cc3eb8999bd9 (patch)
tree53ca1a3df6c81e2eb309b431f01825496ea4692a /hw/usb-musb.c
parentd47e59b8b8adc96a2052f7e004cb12b6ff62edd9 (diff)
usb: Replace device_destroy bus op with a child_detach port op
Note this fixes 2 things in one go, first of all the device_destroy bus op should be a device_detach bus op, as pending async packets from the device should be cancelled on detach not on destroy. Secondly having this as a bus op won't work with companion controllers, since then there will be 1 bus driven by the ehci controller and thus 1 set of bus ops, but the device being detached may be downstream of a handed over port. Making the detach of a downstream device a port op allows the ehci controller to forward this to the companion controller port for handed over ports. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb-musb.c')
-rw-r--r--hw/usb-musb.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 580bdc815a..035dda8372 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -261,17 +261,18 @@
static void musb_attach(USBPort *port);
static void musb_detach(USBPort *port);
+static void musb_child_detach(USBPort *port, USBDevice *child);
static void musb_schedule_cb(USBPort *port, USBPacket *p);
-static void musb_device_destroy(USBBus *bus, USBDevice *dev);
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
static USBPortOps musb_port_ops = {
.attach = musb_attach,
.detach = musb_detach,
+ .child_detach = musb_child_detach,
.complete = musb_schedule_cb,
};
static USBBusOps musb_bus_ops = {
- .device_destroy = musb_device_destroy,
};
typedef struct MUSBPacket MUSBPacket;
@@ -497,10 +498,19 @@ static void musb_detach(USBPort *port)
{
MUSBState *s = (MUSBState *) port->opaque;
+ musb_async_cancel_device(s, port->dev);
+
musb_intr_set(s, musb_irq_disconnect, 1);
musb_session_update(s, 1, s->session);
}
+static void musb_child_detach(USBPort *port, USBDevice *child)
+{
+ MUSBState *s = (MUSBState *) port->opaque;
+
+ musb_async_cancel_device(s, child);
+}
+
static void musb_cb_tick0(void *opaque)
{
MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
@@ -782,9 +792,8 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
musb_rx_intr_set(s, epnum, 1);
}
-static void musb_device_destroy(USBBus *bus, USBDevice *dev)
+static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
{
- MUSBState *s = container_of(bus, MUSBState, bus);
int ep, dir;
for (ep = 0; ep < 16; ep++) {