diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-08-29 13:08:04 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-08-29 13:08:04 +0100 |
commit | d9aa68855724752a5684c6acfb17d8db15cec2f8 (patch) | |
tree | 758d5c6bb19c65ddc8d63868b112aa251a9c6059 /hw | |
parent | a6aebb38ba4682951ab04fe6d6e6b169bd9e4dca (diff) | |
parent | 25e89ec5d2c7f8d953cb1ca558afa74974ff8930 (diff) |
Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20140829-1' into staging
usb: bugfix collection.
usb: add cleanup functions for host adapters,
in preparation for hotplug support.
usb: add simple qtests for uhci,ohci,xhci.
# gpg: Signature made Fri 29 Aug 2014 12:56:20 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
* remotes/kraxel/tags/pull-usb-20140829-1:
tests: add xHCI qtest
tests: add UHCI qtest
tests: add OHCI qtest
usb: add usb host adapters exit trace
usb-xhci: add exit function
usb-ehci: add ehci-pci device exit function
usb-ehci: add ehci unrealize funciton
usb-ehci: add vmstate properity for EHCIState
usb-uhci: clean up uhci resource when pci-uhci exit
usb-ohci: add exit function
usb-ohci: Fix memory leak for ohci timer
usb: add usb_bus_release function
Revert "xhci: Fix number of streams allocated when using streams"
xhci: use (1u << i)
Fix OHCI ISO TD state never being written back.
xhci: fix debug print compiling error
usb: Fix bootindex for portnr > 9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/usb/bus.c | 11 | ||||
-rw-r--r-- | hw/usb/hcd-ehci-pci.c | 14 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 29 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.h | 2 | ||||
-rw-r--r-- | hw/usb/hcd-ohci.c | 27 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 24 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 50 |
7 files changed, 145 insertions, 12 deletions
diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 927a47bbff..c7c4dadedd 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -87,6 +87,13 @@ void usb_bus_new(USBBus *bus, size_t bus_size, QTAILQ_INSERT_TAIL(&busses, bus, next); } +void usb_bus_release(USBBus *bus) +{ + assert(next_usb_bus > 0); + + QTAILQ_REMOVE(&busses, bus, next); +} + USBBus *usb_bus_find(int busnr) { USBBus *bus; @@ -589,11 +596,11 @@ static char *usb_get_fw_dev_path(DeviceState *qdev) nr = strtol(in, &in, 10); if (in[0] == '.') { /* some hub between root port and device */ - pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr); + pos += snprintf(fw_path + pos, fw_len - pos, "hub@%lx/", nr); in++; } else { /* the device itself */ - pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld", + pos += snprintf(fw_path + pos, fw_len - pos, "%s@%lx", qdev_fw_name(qdev), nr); break; } diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 505741a783..289ca3b853 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -84,6 +84,19 @@ static void usb_ehci_pci_init(Object *obj) usb_ehci_init(s, DEVICE(obj)); } +static void usb_ehci_pci_exit(PCIDevice *dev) +{ + EHCIPCIState *i = PCI_EHCI(dev); + EHCIState *s = &i->ehci; + + usb_ehci_unrealize(s, DEVICE(dev), NULL); + + if (s->irq) { + g_free(s->irq); + s->irq = NULL; + } +} + static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int l) { @@ -121,6 +134,7 @@ static void ehci_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->init = usb_ehci_pci_initfn; + k->exit = usb_ehci_pci_exit; k->class_id = PCI_CLASS_SERIAL_USB; k->config_write = usb_ehci_pci_write_config; dc->hotpluggable = false; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 448e0073dd..bacb7ceac9 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2468,7 +2468,34 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) s->device = dev; qemu_register_reset(ehci_reset, s); - qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); + s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s); +} + +void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp) +{ + trace_usb_ehci_unrealize(); + + if (s->frame_timer) { + timer_del(s->frame_timer); + timer_free(s->frame_timer); + s->frame_timer = NULL; + } + if (s->async_bh) { + qemu_bh_delete(s->async_bh); + } + + ehci_queues_rip_all(s, 0); + ehci_queues_rip_all(s, 1); + + memory_region_del_subregion(&s->mem, &s->mem_caps); + memory_region_del_subregion(&s->mem, &s->mem_opreg); + memory_region_del_subregion(&s->mem, &s->mem_ports); + + usb_bus_release(&s->bus); + + if (s->vmstate) { + qemu_del_vm_change_state_handler(s->vmstate); + } } void usb_ehci_init(EHCIState *s, DeviceState *dev) diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 1ad4b96cce..4858b7e80c 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -316,12 +316,14 @@ struct EHCIState { uint32_t async_stepdown; uint32_t periodic_sched_active; bool int_req_by_async; + VMChangeStateEntry *vmstate; }; extern const VMStateDescription vmstate_ehci; void usb_ehci_init(EHCIState *s, DeviceState *dev); void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp); +void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp); #define TYPE_PCI_EHCI "pci-ehci-usb" #define PCI_EHCI(obj) OBJECT_CHECK(EHCIPCIState, (obj), TYPE_PCI_EHCI) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 13afdf5919..83bec34185 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -619,8 +619,8 @@ static inline int ohci_put_td(OHCIState *ohci, static inline int ohci_put_iso_td(OHCIState *ohci, dma_addr_t addr, struct ohci_iso_td *td) { - return put_dwords(ohci, addr, (uint32_t *)td, 4 || - put_words(ohci, addr + 16, td->offset, 8)); + return put_dwords(ohci, addr, (uint32_t *)td, 4) || + put_words(ohci, addr + 16, td->offset, 8); } static inline int ohci_put_hcca(OHCIState *ohci, @@ -1371,8 +1371,10 @@ static int ohci_bus_start(OHCIState *ohci) /* Stop sending SOF tokens on the bus */ static void ohci_bus_stop(OHCIState *ohci) { - if (ohci->eof_timer) + if (ohci->eof_timer) { timer_del(ohci->eof_timer); + timer_free(ohci->eof_timer); + } ohci->eof_timer = NULL; } @@ -1952,6 +1954,24 @@ static int usb_ohci_initfn_pci(PCIDevice *dev) return 0; } +static void usb_ohci_exit(PCIDevice *dev) +{ + OHCIPCIState *ohci = PCI_OHCI(dev); + OHCIState *s = &ohci->state; + + ohci_bus_stop(s); + + if (s->async_td) { + usb_cancel_packet(&s->usb_packet); + s->async_td = 0; + } + ohci_stop_endpoints(s); + + if (!ohci->masterbus) { + usb_bus_release(&s->bus); + } +} + #define TYPE_SYSBUS_OHCI "sysbus-ohci" #define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI) @@ -2089,6 +2109,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->init = usb_ohci_initfn_pci; + k->exit = usb_ohci_exit; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; k->class_id = PCI_CLASS_SERIAL_USB; diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index ee5f112d65..3b3ebcda8b 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1256,6 +1256,29 @@ static int usb_uhci_vt82c686b_initfn(PCIDevice *dev) return usb_uhci_common_initfn(dev); } +static void usb_uhci_exit(PCIDevice *dev) +{ + UHCIState *s = DO_UPCAST(UHCIState, dev, dev); + + trace_usb_uhci_exit(); + + if (s->frame_timer) { + timer_del(s->frame_timer); + timer_free(s->frame_timer); + s->frame_timer = NULL; + } + + if (s->bh) { + qemu_bh_delete(s->bh); + } + + uhci_async_cancel_all(s); + + if (!s->masterbus) { + usb_bus_release(&s->bus); + } +} + static Property uhci_properties[] = { DEFINE_PROP_STRING("masterbus", UHCIState, masterbus), DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0), @@ -1272,6 +1295,7 @@ static void uhci_class_init(ObjectClass *klass, void *data) UHCIInfo *info = data; k->init = info->initfn ? info->initfn : usb_uhci_common_initfn; + k->exit = info->unplug ? usb_uhci_exit : NULL; k->vendor_id = info->vendor_id; k->device_id = info->device_id; k->revision = info->revision; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 58c4b11527..bbe4c5fb85 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1151,7 +1151,7 @@ static void xhci_reset_streams(XHCIEPContext *epctx) static void xhci_alloc_streams(XHCIEPContext *epctx, dma_addr_t base) { assert(epctx->pstreams == NULL); - epctx->nr_pstreams = 2 << (epctx->max_pstreams + 1); + epctx->nr_pstreams = 2 << epctx->max_pstreams; epctx->pstreams = xhci_alloc_stream_contexts(epctx->nr_pstreams, base); } @@ -1180,7 +1180,7 @@ static int xhci_epmask_to_eps_with_streams(XHCIState *xhci, slot = &xhci->slots[slotid - 1]; for (i = 2, j = 0; i <= 31; i++) { - if (!(epmask & (1 << i))) { + if (!(epmask & (1u << i))) { continue; } @@ -1380,14 +1380,11 @@ static void xhci_init_epctx(XHCIEPContext *epctx, dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]); epctx->type = (ctx[1] >> EP_TYPE_SHIFT) & EP_TYPE_MASK; - DPRINTF("xhci: endpoint %d.%d type is %d\n", epid/2, epid%2, epctx->type); epctx->pctx = pctx; epctx->max_psize = ctx[1]>>16; epctx->max_psize *= 1+((ctx[1]>>8)&0xff); epctx->max_pstreams = (ctx[0] >> 10) & 0xf; epctx->lsa = (ctx[0] >> 15) & 1; - DPRINTF("xhci: endpoint %d.%d max transaction (burst) size is %d\n", - epid/2, epid%2, epctx->max_psize); if (epctx->max_pstreams) { xhci_alloc_streams(epctx, dequeue); } else { @@ -1418,6 +1415,9 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, slot->eps[epid-1] = epctx; xhci_init_epctx(epctx, pctx, ctx); + DPRINTF("xhci: endpoint %d.%d type is %d, max transaction (burst) " + "size is %d\n", epid/2, epid%2, epctx->type, epctx->max_psize); + epctx->mfindex_last = 0; epctx->state = EP_RUNNING; @@ -2465,7 +2465,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, res = xhci_alloc_device_streams(xhci, slotid, ictl_ctx[1]); if (res != CC_SUCCESS) { for (i = 2; i <= 31; i++) { - if (ictl_ctx[1] & (1 << i)) { + if (ictl_ctx[1] & (1u << i)) { xhci_disable_ep(xhci, slotid, i); } } @@ -3644,6 +3644,43 @@ static int usb_xhci_initfn(struct PCIDevice *dev) return 0; } +static void usb_xhci_exit(PCIDevice *dev) +{ + int i; + XHCIState *xhci = XHCI(dev); + + trace_usb_xhci_exit(); + + 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 +3873,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; |