int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags) { struct xhci_virt_device *dev; int i; /* Slot ID 0 is reserved */ if (slot_id == 0 || xhci->devs[slot_id]) { xhci_warn(xhci, "Bad Slot ID %d\n", slot_id); return 0; } xhci->devs[slot_id] = kzalloc(sizeof(*xhci->devs[slot_id]), flags); if (!xhci->devs[slot_id]) return 0; dev = xhci->devs[slot_id]; /* Allocate the (output) device context that will be used in the HC. */ dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags); if (!dev->out_ctx) goto fail; xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->out_ctx->dma); /* Allocate the (input) device context for address device command */ dev->in_ctx = xhci_alloc_container_ctx(xhci, (XHCI_CTX_TYPE_INPUT), flags); if (!dev->in_ctx) goto fail; xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->in_ctx->dma); /* Initialize the cancellation list for each endpoint */ for (i = 0; i < 31; i++) INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); /* Allocate endpoint 0 ring */ dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, flags); if (!dev->eps[0].ring) goto fail; init_completion(&dev->cmd_completion); INIT_LIST_HEAD(&dev->cmd_list); /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = SWAP64(dev->out_ctx->dma); xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", slot_id, &xhci->dcbaa->dev_context_ptrs[slot_id], SWAP64((unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id])); return 1; fail: xhci_free_virt_device(xhci, slot_id); return 0; }
/** * Allocating virtual device * * @param udev pointer to USB deivce structure * @return 0 on success else -1 on failure */ int xhci_alloc_virt_device(struct usb_device *udev) { u64 byte_64 = 0; unsigned int slot_id = udev->slot_id; struct xhci_virt_device *virt_dev; struct xhci_ctrl *ctrl = udev->controller; /* Slot ID 0 is reserved */ if (ctrl->devs[slot_id]) { printf("Virt dev for slot[%d] already allocated\n", slot_id); return -EEXIST; } ctrl->devs[slot_id] = (struct xhci_virt_device *) malloc(sizeof(struct xhci_virt_device)); if (!ctrl->devs[slot_id]) { puts("Failed to allocate virtual device\n"); return -ENOMEM; } memset(ctrl->devs[slot_id], 0, sizeof(struct xhci_virt_device)); virt_dev = ctrl->devs[slot_id]; /* Allocate the (output) device context that will be used in the HC. */ virt_dev->out_ctx = xhci_alloc_container_ctx(ctrl, XHCI_CTX_TYPE_DEVICE); if (!virt_dev->out_ctx) { puts("Failed to allocate out context for virt dev\n"); return -ENOMEM; } /* Allocate the (input) device context for address device command */ virt_dev->in_ctx = xhci_alloc_container_ctx(ctrl, XHCI_CTX_TYPE_INPUT); if (!virt_dev->in_ctx) { puts("Failed to allocate in context for virt dev\n"); return -ENOMEM; } /* Allocate endpoint 0 ring */ virt_dev->eps[0].ring = xhci_ring_alloc(1, true); byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); /* Point to output device context in dcbaa. */ ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; xhci_flush_cache((uint32_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], sizeof(__le64)); return 0; }
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags) { struct xhci_virt_device *dev; /* Slot ID 0 is reserved */ if (slot_id == 0 || xhci->devs[slot_id]) { xhci_warn(xhci, "Bad Slot ID %d\n", slot_id); return 0; } xhci->devs[slot_id] = kzalloc(sizeof(*xhci->devs[slot_id]), flags); if (!xhci->devs[slot_id]) return 0; dev = xhci->devs[slot_id]; /* Allocate the (output) device context that will be used in the HC. */ dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags); if (!dev->out_ctx) goto fail; xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->out_ctx->dma); /* Allocate the (input) device context for address device command */ dev->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, flags); if (!dev->in_ctx) goto fail; xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->in_ctx->dma); /* Allocate endpoint 0 ring */ dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags); if (!dev->ep_rings[0]) goto fail; init_completion(&dev->cmd_completion); /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", slot_id, &xhci->dcbaa->dev_context_ptrs[slot_id], (unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]); UBI_DMA_FLUSH(&xhci->dcbaa->dev_context_ptrs[slot_id], sizeof(u64)); return 1; fail: xhci_free_virt_device(xhci, slot_id); return 0; }