diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2009-09-25 21:42:39 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-10-05 09:32:48 -0500 |
commit | a8e662b5477a7e3659c7fc2d83db50c42b201c1d (patch) | |
tree | 12dcfa0a4ef0960eec14ff44b772c8e0a5e80061 /hw | |
parent | e3936fa574d9fbe241acdc76b5195b048567537e (diff) |
usb: hook unplug into qdev, cleanups + fixes.
Hook into DeviceInfo->exit().
handle_destroy() must not free the state struct, this is handled
by the new usb_qdev_exit() function now.
qdev_free(usb_device) works now.
Fix usb hub to qdev_free() all connected devices on unplug.
Unplugging a usb hub works now.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/usb-bt.c | 1 | ||||
-rw-r--r-- | hw/usb-bus.c | 57 | ||||
-rw-r--r-- | hw/usb-hid.c | 1 | ||||
-rw-r--r-- | hw/usb-hub.c | 6 | ||||
-rw-r--r-- | hw/usb-msd.c | 2 | ||||
-rw-r--r-- | hw/usb-serial.c | 1 | ||||
-rw-r--r-- | hw/usb-wacom.c | 1 | ||||
-rw-r--r-- | hw/usb.h | 2 |
8 files changed, 56 insertions, 15 deletions
diff --git a/hw/usb-bt.c b/hw/usb-bt.c index 70fd4dd533..18d7a98b43 100644 --- a/hw/usb-bt.c +++ b/hw/usb-bt.c @@ -614,7 +614,6 @@ static void usb_bt_handle_destroy(USBDevice *dev) s->hci->opaque = NULL; s->hci->evt_recv = NULL; s->hci->acl_recv = NULL; - qemu_free(s); } static int usb_bt_initfn(USBDevice *dev) diff --git a/hw/usb-bus.c b/hw/usb-bus.c index 2cac1e85b7..d0b59dd4dd 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -50,10 +50,22 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) return rc; } +static int usb_qdev_exit(DeviceState *qdev) +{ + USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + + usb_device_detach(dev); + if (dev->info->handle_destroy) { + dev->info->handle_destroy(dev); + } + return 0; +} + void usb_qdev_register(USBDeviceInfo *info) { info->qdev.bus_info = &usb_bus_info; info->qdev.init = usb_qdev_init; + info->qdev.exit = usb_qdev_exit; qdev_register(&info->qdev); } @@ -101,6 +113,14 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, bus->nfree++; } +void usb_unregister_port(USBBus *bus, USBPort *port) +{ + if (port->dev) + qdev_free(&port->dev->qdev); + QTAILQ_REMOVE(&bus->free, port, next); + bus->nfree--; +} + static void do_attach(USBDevice *dev) { USBBus *bus = usb_bus_from_device(dev); @@ -136,6 +156,34 @@ int usb_device_attach(USBDevice *dev) return 0; } +int usb_device_detach(USBDevice *dev) +{ + USBBus *bus = usb_bus_from_device(dev); + USBPort *port; + + if (!dev->attached) { + fprintf(stderr, "Warning: tried to detach unattached usb device %s\n", + dev->devname); + return -1; + } + dev->attached--; + + QTAILQ_FOREACH(port, &bus->used, next) { + if (port->dev == dev) + break; + } + assert(port != NULL); + + QTAILQ_REMOVE(&bus->used, port, next); + bus->nused--; + + usb_attach(port, NULL); + + QTAILQ_INSERT_TAIL(&bus->free, port, next); + bus->nfree++; + return 0; +} + int usb_device_delete_addr(int busnr, int addr) { USBBus *bus; @@ -152,16 +200,9 @@ int usb_device_delete_addr(int busnr, int addr) } if (!port) return -1; - dev = port->dev; - QTAILQ_REMOVE(&bus->used, port, next); - bus->nused--; - - usb_attach(port, NULL); - dev->info->handle_destroy(dev); - QTAILQ_INSERT_TAIL(&bus->free, port, next); - bus->nfree++; + qdev_free(&dev->qdev); return 0; } diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 3bf06fa411..d1cc45e02c 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -843,7 +843,6 @@ static void usb_hid_handle_destroy(USBDevice *dev) if (s->kind != USB_KEYBOARD) qemu_remove_mouse_event_handler(s->ptr.eh_entry); /* TODO: else */ - qemu_free(s); } static int usb_hid_initfn(USBDevice *dev, int kind) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 0a39986468..e5a0938776 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -517,8 +517,12 @@ static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p) static void usb_hub_handle_destroy(USBDevice *dev) { USBHubState *s = (USBHubState *)dev; + int i; - qemu_free(s); + for (i = 0; i < s->nb_ports; i++) { + usb_unregister_port(usb_bus_from_device(dev), + &s->ports[i].port); + } } static int usb_hub_initfn(USBDevice *dev) diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 6b9c8a5bdd..843a22f4e4 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -512,9 +512,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) { MSDState *s = (MSDState *)dev; - s->scsi_dev->info->destroy(s->scsi_dev); drive_uninit(s->dinfo->bdrv); - qemu_free(s); } static int usb_msd_initfn(USBDevice *dev) diff --git a/hw/usb-serial.c b/hw/usb-serial.c index 091ab2cbc1..e2379c4d5e 100644 --- a/hw/usb-serial.c +++ b/hw/usb-serial.c @@ -486,7 +486,6 @@ static void usb_serial_handle_destroy(USBDevice *dev) USBSerialState *s = (USBSerialState *)dev; qemu_chr_close(s->cs); - qemu_free(s); } static int usb_serial_can_read(void *opaque) diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c index 55f06bfd99..3ea72411a1 100644 --- a/hw/usb-wacom.c +++ b/hw/usb-wacom.c @@ -389,7 +389,6 @@ static void usb_wacom_handle_destroy(USBDevice *dev) USBWacomState *s = (USBWacomState *) dev; qemu_remove_mouse_event_handler(s->eh_entry); - qemu_free(s); } static int usb_wacom_initfn(USBDevice *dev) @@ -311,7 +311,9 @@ USBDevice *usb_create(USBBus *bus, const char *name); USBDevice *usb_create_simple(USBBus *bus, const char *name); void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, usb_attachfn attach); +void usb_unregister_port(USBBus *bus, USBPort *port); int usb_device_attach(USBDevice *dev); +int usb_device_detach(USBDevice *dev); int usb_device_delete_addr(int busnr, int addr); static inline USBBus *usb_bus_from_device(USBDevice *d) |