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>
This commit is contained in:
		
							parent
							
								
									e3936fa574
								
							
						
					
					
						commit
						a8e662b547
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										57
									
								
								hw/usb-bus.c
								
								
								
								
							
							
						
						
									
										57
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								hw/usb.h
								
								
								
								
							
							
						
						
									
										2
									
								
								hw/usb.h
								
								
								
								
							| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue