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; }
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_device *udev, struct usb_host_endpoint *ep, gfp_t mem_flags) { unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; struct xhci_ring *ep_ring; unsigned int max_packet; unsigned int max_burst; ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); /* Set up the endpoint ring */ virt_dev->eps[ep_index].new_ring = xhci_ring_alloc(xhci, 1, true, mem_flags); if (!virt_dev->eps[ep_index].new_ring) { /* Attempt to use the ring cache */ if (virt_dev->num_rings_cached == 0) return -ENOMEM; virt_dev->eps[ep_index].new_ring = virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; virt_dev->num_rings_cached--; xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring); } ep_ring = virt_dev->eps[ep_index].new_ring; ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); /* FIXME dig Mult and streams info out of ep companion desc */ /* Allow 3 retries for everything but isoc; * error count = 0 means infinite retries. */ if (!usb_endpoint_xfer_isoc(&ep->desc)) ep_ctx->ep_info2 = ERROR_COUNT(3); else ep_ctx->ep_info2 = ERROR_COUNT(1); ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep); /* Set the max packet size and max burst */ switch (udev->speed) { case USB_SPEED_SUPER: max_packet = ep->desc.wMaxPacketSize; ep_ctx->ep_info2 |= MAX_PACKET(max_packet); /* dig out max burst from ep companion desc */ if (!ep->ss_ep_comp) { xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n"); max_packet = 0; } else { max_packet = ep->ss_ep_comp->desc.bMaxBurst; } ep_ctx->ep_info2 |= MAX_BURST(max_packet); break; case USB_SPEED_HIGH: /* bits 11:12 specify the number of additional transaction * opportunities per microframe (USB 2.0, section 9.6.6) */ if (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) { max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11; ep_ctx->ep_info2 |= MAX_BURST(max_burst); } /* Fall through */ case USB_SPEED_FULL: case USB_SPEED_LOW: max_packet = ep->desc.wMaxPacketSize & 0x3ff; ep_ctx->ep_info2 |= MAX_PACKET(max_packet); break; default: BUG(); }
/** * Allocates the necessary data structures * for XHCI host controller * * @param ctrl Host controller data structure * @param hccr pointer to HOST Controller Control Registers * @param hcor pointer to HOST Controller Operational Registers * @return 0 if successful else -1 on failure */ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, struct xhci_hcor *hcor) { uint64_t val_64; uint64_t trb_64; uint32_t val; unsigned long deq; int i; struct xhci_segment *seg; /* DCBAA initialization */ ctrl->dcbaa = (struct xhci_device_context_array *) xhci_malloc(sizeof(struct xhci_device_context_array)); if (ctrl->dcbaa == NULL) { puts("unable to allocate DCBA\n"); return -ENOMEM; } val_64 = (uintptr_t)ctrl->dcbaa; /* Set the pointer in DCBAA register */ xhci_writeq(&hcor->or_dcbaap, val_64); /* Command ring control pointer register initialization */ ctrl->cmd_ring = xhci_ring_alloc(1, true); /* Set the address in the Command Ring Control register */ trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; val_64 = xhci_readq(&hcor->or_crcr); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | ctrl->cmd_ring->cycle_state; xhci_writeq(&hcor->or_crcr, val_64); /* write the address of db register */ val = xhci_readl(&hccr->cr_dboff); val &= DBOFF_MASK; ctrl->dba = (struct xhci_doorbell_array *)((char *)hccr + val); /* write the address of runtime register */ val = xhci_readl(&hccr->cr_rtsoff); val &= RTSOFF_MASK; ctrl->run_regs = (struct xhci_run_regs *)((char *)hccr + val); /* writting the address of ir_set structure */ ctrl->ir_set = &ctrl->run_regs->ir_set[0]; /* Event ring does not maintain link TRB */ ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false); ctrl->erst.entries = (struct xhci_erst_entry *) xhci_malloc(sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); ctrl->erst.num_entries = ERST_NUM_SEGS; for (val = 0, seg = ctrl->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { trb_64 = 0; trb_64 = (uintptr_t)seg->trbs; struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; xhci_writeq(&entry->seg_addr, trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; seg = seg->next; } xhci_flush_cache((uint32_t)ctrl->erst.entries, ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); deq = (unsigned long)ctrl->event_ring->dequeue; /* Update HC event ring dequeue pointer */ xhci_writeq(&ctrl->ir_set->erst_dequeue, (u64)deq & (u64)~ERST_PTR_MASK); /* set ERST count with the number of entries in the segment table */ val = xhci_readl(&ctrl->ir_set->erst_size); val &= ERST_SIZE_MASK; val |= ERST_NUM_SEGS; xhci_writel(&ctrl->ir_set->erst_size, val); /* this is the event ring segment table pointer */ val_64 = xhci_readq(&ctrl->ir_set->erst_base); val_64 &= ERST_PTR_MASK; val_64 |= ((u32)(ctrl->erst.entries) & ~ERST_PTR_MASK); xhci_writeq(&ctrl->ir_set->erst_base, val_64); /* initializing the virtual devices to NULL */ for (i = 0; i < MAX_HC_SLOTS; ++i) ctrl->devs[i] = NULL; /* * Just Zero'ing this register completely, * or some spurious Device Notification Events * might screw things here. */ xhci_writel(&hcor->or_dnctrl, 0x0); return 0; }