summaryrefslogtreecommitdiffstats
path: root/hw/usb/hcd-xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/hcd-xhci.c')
-rw-r--r--hw/usb/hcd-xhci.c50
1 files changed, 44 insertions, 6 deletions
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;