提交 a8e662b5 编写于 作者: G Gerd Hoffmann 提交者: Anthony Liguori

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: NGerd Hoffmann <kraxel@redhat.com>
Signed-off-by: NAnthony Liguori <aliguori@us.ibm.com>
上级 e3936fa5
...@@ -614,7 +614,6 @@ static void usb_bt_handle_destroy(USBDevice *dev) ...@@ -614,7 +614,6 @@ static void usb_bt_handle_destroy(USBDevice *dev)
s->hci->opaque = NULL; s->hci->opaque = NULL;
s->hci->evt_recv = NULL; s->hci->evt_recv = NULL;
s->hci->acl_recv = NULL; s->hci->acl_recv = NULL;
qemu_free(s);
} }
static int usb_bt_initfn(USBDevice *dev) static int usb_bt_initfn(USBDevice *dev)
......
...@@ -50,10 +50,22 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) ...@@ -50,10 +50,22 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
return rc; 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) void usb_qdev_register(USBDeviceInfo *info)
{ {
info->qdev.bus_info = &usb_bus_info; info->qdev.bus_info = &usb_bus_info;
info->qdev.init = usb_qdev_init; info->qdev.init = usb_qdev_init;
info->qdev.exit = usb_qdev_exit;
qdev_register(&info->qdev); qdev_register(&info->qdev);
} }
...@@ -101,6 +113,14 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, ...@@ -101,6 +113,14 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
bus->nfree++; 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) static void do_attach(USBDevice *dev)
{ {
USBBus *bus = usb_bus_from_device(dev); USBBus *bus = usb_bus_from_device(dev);
...@@ -136,6 +156,34 @@ int usb_device_attach(USBDevice *dev) ...@@ -136,6 +156,34 @@ int usb_device_attach(USBDevice *dev)
return 0; 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) int usb_device_delete_addr(int busnr, int addr)
{ {
USBBus *bus; USBBus *bus;
...@@ -152,16 +200,9 @@ int usb_device_delete_addr(int busnr, int addr) ...@@ -152,16 +200,9 @@ int usb_device_delete_addr(int busnr, int addr)
} }
if (!port) if (!port)
return -1; return -1;
dev = port->dev; 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); qdev_free(&dev->qdev);
bus->nfree++;
return 0; return 0;
} }
......
...@@ -843,7 +843,6 @@ static void usb_hid_handle_destroy(USBDevice *dev) ...@@ -843,7 +843,6 @@ static void usb_hid_handle_destroy(USBDevice *dev)
if (s->kind != USB_KEYBOARD) if (s->kind != USB_KEYBOARD)
qemu_remove_mouse_event_handler(s->ptr.eh_entry); qemu_remove_mouse_event_handler(s->ptr.eh_entry);
/* TODO: else */ /* TODO: else */
qemu_free(s);
} }
static int usb_hid_initfn(USBDevice *dev, int kind) static int usb_hid_initfn(USBDevice *dev, int kind)
......
...@@ -517,8 +517,12 @@ static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p) ...@@ -517,8 +517,12 @@ static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
static void usb_hub_handle_destroy(USBDevice *dev) static void usb_hub_handle_destroy(USBDevice *dev)
{ {
USBHubState *s = (USBHubState *)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) static int usb_hub_initfn(USBDevice *dev)
......
...@@ -512,9 +512,7 @@ static void usb_msd_handle_destroy(USBDevice *dev) ...@@ -512,9 +512,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
{ {
MSDState *s = (MSDState *)dev; MSDState *s = (MSDState *)dev;
s->scsi_dev->info->destroy(s->scsi_dev);
drive_uninit(s->dinfo->bdrv); drive_uninit(s->dinfo->bdrv);
qemu_free(s);
} }
static int usb_msd_initfn(USBDevice *dev) static int usb_msd_initfn(USBDevice *dev)
......
...@@ -486,7 +486,6 @@ static void usb_serial_handle_destroy(USBDevice *dev) ...@@ -486,7 +486,6 @@ static void usb_serial_handle_destroy(USBDevice *dev)
USBSerialState *s = (USBSerialState *)dev; USBSerialState *s = (USBSerialState *)dev;
qemu_chr_close(s->cs); qemu_chr_close(s->cs);
qemu_free(s);
} }
static int usb_serial_can_read(void *opaque) static int usb_serial_can_read(void *opaque)
......
...@@ -389,7 +389,6 @@ static void usb_wacom_handle_destroy(USBDevice *dev) ...@@ -389,7 +389,6 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
USBWacomState *s = (USBWacomState *) dev; USBWacomState *s = (USBWacomState *) dev;
qemu_remove_mouse_event_handler(s->eh_entry); qemu_remove_mouse_event_handler(s->eh_entry);
qemu_free(s);
} }
static int usb_wacom_initfn(USBDevice *dev) static int usb_wacom_initfn(USBDevice *dev)
......
...@@ -311,7 +311,9 @@ USBDevice *usb_create(USBBus *bus, const char *name); ...@@ -311,7 +311,9 @@ USBDevice *usb_create(USBBus *bus, const char *name);
USBDevice *usb_create_simple(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, void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
usb_attachfn attach); usb_attachfn attach);
void usb_unregister_port(USBBus *bus, USBPort *port);
int usb_device_attach(USBDevice *dev); int usb_device_attach(USBDevice *dev);
int usb_device_detach(USBDevice *dev);
int usb_device_delete_addr(int busnr, int addr); int usb_device_delete_addr(int busnr, int addr);
static inline USBBus *usb_bus_from_device(USBDevice *d) static inline USBBus *usb_bus_from_device(USBDevice *d)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册