aboutsummaryrefslogtreecommitdiff
path: root/hw/usb
diff options
context:
space:
mode:
authorGonglei <arei.gonglei@huawei.com>2014-06-04 16:31:53 +0800
committerGerd Hoffmann <kraxel@redhat.com>2014-08-29 12:52:14 +0200
commit53c30545fb34c43c84d62ea1c2b0dc6b53303c34 (patch)
tree63179a8e20de679a9a64bd57e6ace62ff484da78 /hw/usb
parent96e14926c66dc7da99bea80d639a30cce0772991 (diff)
downloadqemu-53c30545fb34c43c84d62ea1c2b0dc6b53303c34.zip
qemu-53c30545fb34c43c84d62ea1c2b0dc6b53303c34.tar.gz
qemu-53c30545fb34c43c84d62ea1c2b0dc6b53303c34.tar.bz2
usb-xhci: add exit function
clean up xhci resource when xhci pci device exit. Signed-off-by: Gonglei <arei.gonglei@huawei.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb')
-rw-r--r--hw/usb/hcd-xhci.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 88660e8..a9245d8 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3644,6 +3644,41 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
return 0;
}
+static void usb_xhci_exit(PCIDevice *dev)
+{
+ int i;
+ XHCIState *xhci = XHCI(dev);
+
+ for (i = 0; i < xhci->numslots; i++) {
+ xhci_disable_slot(xhci, i + 1);
+ }
+
+ if (xhci->mfwrap_timer) {
+ timer_del(xhci->mfwrap_timer);
+ timer_free(xhci->mfwrap_timer);
+ xhci->mfwrap_timer = NULL;
+ }
+
+ memory_region_del_subregion(&xhci->mem, &xhci->mem_cap);
+ memory_region_del_subregion(&xhci->mem, &xhci->mem_oper);
+ memory_region_del_subregion(&xhci->mem, &xhci->mem_runtime);
+ memory_region_del_subregion(&xhci->mem, &xhci->mem_doorbell);
+
+ for (i = 0; i < xhci->numports; i++) {
+ XHCIPort *port = &xhci->ports[i];
+ memory_region_del_subregion(&xhci->mem, &port->mem);
+ }
+
+ /* destroy msix memory region */
+ if (dev->msix_table && dev->msix_pba
+ && dev->msix_entry_used) {
+ memory_region_del_subregion(&xhci->mem, &dev->msix_table_mmio);
+ memory_region_del_subregion(&xhci->mem, &dev->msix_pba_mmio);
+ }
+
+ usb_bus_release(&xhci->bus);
+}
+
static int usb_xhci_post_load(void *opaque, int version_id)
{
XHCIState *xhci = opaque;
@@ -3836,6 +3871,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
k->init = usb_xhci_initfn;
+ k->exit = usb_xhci_exit;
k->vendor_id = PCI_VENDOR_ID_NEC;
k->device_id = PCI_DEVICE_ID_NEC_UPD720200;
k->class_id = PCI_CLASS_SERIAL_USB;