void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep) { int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; dma_addr_t dma = ctx->dma; int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); if (ctx->type == XHCI_CTX_TYPE_INPUT) { struct xhci_input_control_ctx *ctrl_ctx = xhci_get_input_control_ctx(xhci, ctx); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", &ctrl_ctx->drop_flags, (unsigned long long)dma, ctrl_ctx->drop_flags); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", &ctrl_ctx->add_flags, (unsigned long long)dma, ctrl_ctx->add_flags); dma += field_size; for (i = 0; i < 6; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", &ctrl_ctx->rsvd2[i], (unsigned long long)dma, ctrl_ctx->rsvd2[i], i); dma += field_size; } if (csz) dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); }
int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) { int i; int ret = 0; struct xhci_hcd *xhci; struct xhci_virt_device *virt_dev; struct xhci_input_control_ctx *ctrl_ctx; struct xhci_slot_ctx *slot_ctx; ret = xhci_check_args(hcd, udev, NULL, 0, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); if (!udev->slot_id || !xhci->devs || !xhci->devs[udev->slot_id]) { xhci_warn(xhci, "xHCI %s called with unaddressed device\n", __func__); return -EINVAL; } xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx->add_flags |= SLOT_FLAG; ctrl_ctx->add_flags &= ~EP0_FLAG; ctrl_ctx->drop_flags &= ~SLOT_FLAG; ctrl_ctx->drop_flags &= ~EP0_FLAG; xhci_dbg(xhci, "New Input Control Context:\n"); slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); xhci_dbg_ctx(xhci, virt_dev->in_ctx, LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); ret = xhci_configure_endpoint(xhci, udev, NULL, false, false); if (ret) { return ret; } xhci_dbg(xhci, "Output context after successful config ep cmd:\n"); xhci_dbg_ctx(xhci, virt_dev->out_ctx, LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); xhci_zero_in_ctx(xhci, virt_dev); for (i = 1; i < 31; ++i) { if (virt_dev->eps[i].new_ring) { xhci_ring_free(xhci, virt_dev->eps[i].ring); virt_dev->eps[i].ring = virt_dev->eps[i].new_ring; virt_dev->eps[i].new_ring = NULL; } } return ret; }
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep) { int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; struct xhci_slot_ctx *slot_ctx; dma_addr_t dma = ctx->dma; int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); if (ctx->type == XHCI_CTX_TYPE_INPUT) { struct xhci_input_control_ctx *ctrl_ctx = xhci_get_input_control_ctx(xhci, ctx); #if 0 /* original code */ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", &ctrl_ctx->drop_flags, (unsigned long long)dma, ctrl_ctx->drop_flags); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", &ctrl_ctx->add_flags, (unsigned long long)dma, ctrl_ctx->add_flags); dma += field_size; for (i = 0; i < 6; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", &ctrl_ctx->rsvd2[i], (unsigned long long)dma, ctrl_ctx->rsvd2[i], i); dma += field_size; } #else /* 2010/6/28, modified by Panasonic for little-endian access to the data structures in host memory */ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", &ctrl_ctx->drop_flags, (unsigned long long)dma, xhci_desc_readl(xhci, &ctrl_ctx->drop_flags)); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", &ctrl_ctx->add_flags, (unsigned long long)dma, xhci_desc_readl(xhci, &ctrl_ctx->add_flags)); dma += field_size; for (i = 0; i < 6; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", &ctrl_ctx->rsvd2[i], (unsigned long long)dma, xhci_desc_readl(xhci, &ctrl_ctx->rsvd2[i]), i); dma += field_size; } #endif if (csz) dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } slot_ctx = xhci_get_slot_ctx(xhci, ctx); xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); }
/* Drop an endpoint from a new bandwidth configuration for this device. * Only one call to this function is allowed per endpoint before * check_bandwidth() or reset_bandwidth() must be called. * A call to xhci_drop_endpoint() followed by a call to xhci_add_endpoint() will * add the endpoint to the schedule with possibly new parameters denoted by a * different endpoint descriptor in usb_host_endpoint. * A call to xhci_add_endpoint() followed by a call to xhci_drop_endpoint() is * not allowed. * * The USB core will not allow URBs to be queued to an endpoint that is being * disabled, so there's no need for mutual exclusion to protect * the xhci->devs[slot_id] structure. */ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep) { struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; struct xhci_input_control_ctx *ctrl_ctx; unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; u32 drop_flag; u32 new_add_flags, new_drop_flags; int ret; ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); if (xhci->xhc_state & XHCI_STATE_DYING) return -ENODEV; xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); drop_flag = xhci_get_endpoint_flag(&ep->desc); if (drop_flag == SLOT_FLAG || drop_flag == EP0_FLAG) { xhci_dbg(xhci, "xHCI %s - can't drop slot or ep 0 %#x\n", __func__, drop_flag); return 0; } in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(in_ctx); if (!ctrl_ctx) { xhci_warn(xhci, "%s: Could not get input context, bad type.\n", __func__); return 0; } ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If the HC already knows the endpoint is disabled, * or the HCD has noted it is disabled, ignore this request */ if (((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) == cpu_to_le32(EP_STATE_DISABLED)) || le32_to_cpu(ctrl_ctx->drop_flags) & xhci_get_endpoint_flag(&ep->desc)) { /* Do not warn when called after a usb_device_reset */ if (xhci->devs[udev->slot_id]->eps[ep_index].ring != NULL) xhci_warn(xhci, "xHCI %s called with disabled ep %p\n", __func__, ep); return 0; } ctrl_ctx->drop_flags |= cpu_to_le32(drop_flag); new_drop_flags = le32_t
static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct urb *urb) { struct xhci_container_ctx *in_ctx; struct xhci_container_ctx *out_ctx; struct xhci_input_control_ctx *ctrl_ctx; struct xhci_ep_ctx *ep_ctx; int max_packet_size; int hw_max_packet_size; int ret = 0; out_ctx = xhci->devs[slot_id]->out_ctx; ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2); max_packet_size = urb->dev->ep0.desc.wMaxPacketSize; if (hw_max_packet_size != max_packet_size) { xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n"); xhci_dbg(xhci, "Max packet size in usb_device = %d\n", max_packet_size); xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n", hw_max_packet_size); xhci_dbg(xhci, "Issuing evaluate context command.\n"); xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, xhci->devs[slot_id]->out_ctx, ep_index); in_ctx = xhci->devs[slot_id]->in_ctx; ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); ep_ctx->ep_info2 &= ~MAX_PACKET_MASK; ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size); ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ctrl_ctx->add_flags = EP0_FLAG; ctrl_ctx->drop_flags = 0; xhci_dbg(xhci, "Slot %d input context\n", slot_id); xhci_dbg_ctx(xhci, in_ctx, ep_index); xhci_dbg(xhci, "Slot %d output context\n", slot_id); xhci_dbg_ctx(xhci, out_ctx, ep_index); ret = xhci_configure_endpoint(xhci, urb->dev, NULL, true, false); ctrl_ctx->add_flags = SLOT_FLAG; } return ret; }
static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci, struct xhci_container_ctx *in_ctx, struct xhci_container_ctx *out_ctx, u32 add_flags, u32 drop_flags) { struct xhci_input_control_ctx *ctrl_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ctrl_ctx->add_flags = add_flags; ctrl_ctx->drop_flags = drop_flags; xhci_slot_copy(xhci, in_ctx, out_ctx); ctrl_ctx->add_flags |= SLOT_FLAG; xhci_dbg(xhci, "Input Context:\n"); xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags)); }
static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev) { struct xhci_input_control_ctx *ctrl_ctx; struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; int i; ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx->drop_flags = 0; ctrl_ctx->add_flags = 0; slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); slot_ctx->dev_info &= ~LAST_CTX_MASK; slot_ctx->dev_info |= LAST_CTX(1); for (i = 1; i < 31; ++i) { ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i); ep_ctx->ep_info = 0; ep_ctx->ep_info2 = 0; ep_ctx->deq = 0; ep_ctx->tx_info = 0; } }
/* * Full speed devices may have a max packet size greater than 8 bytes, but the * USB core doesn't know that until it reads the first 8 bytes of the * descriptor. If the usb_device's max packet size changes after that point, * we need to issue an evaluate context command and wait on it. */ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct urb *urb) { struct xhci_container_ctx *out_ctx; struct xhci_input_control_ctx *ctrl_ctx; struct xhci_ep_ctx *ep_ctx; struct xhci_command *command; int max_packet_size; int hw_max_packet_size; int ret = 0; out_ctx = xhci->devs[slot_id]->out_ctx; ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); max_packet_size = usb_endpoint_maxp(&urb->dev->ep0.desc); if (hw_max_packet_size != max_packet_size) { xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, "Max Packet Size for ep 0 changed."); xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, "Max packet size in usb_device = %d", max_packet_size); xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, "Max packet size in xHCI HW = %d", hw_max_packet_size); xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, "Issuing evaluate context command."); /* Set up the input context flags for the command */ /* FIXME: This won't work if a non-default control endpoint * changes max packet sizes. */ command = xhci_alloc_command(xhci, false, true, GFP_KERNEL); if (!command) return -ENOMEM; command->in_ctx = xhci->devs[slot_id]->in_ctx; ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx); if (!ctrl_ctx) { xhci_warn(xhci, "%s: Could not get input context, bad type.\n", __func__); ret = -ENOMEM; goto command_cleanup; } /* Set up the modified control endpoint 0 */ xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, xhci->devs[slot_id]->out_ctx, ep_index); ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index); ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); ctrl_ctx->drop_flags = 0; xhci_dbg(xhci, "Slot %d input context\n", slot_id); xhci_dbg_ctx(xhci, command->in_ctx, ep_index); xhci_dbg(xhci, "Slot %d output context\n", slot_id); xhci_dbg_ctx(xhci, out_ctx, ep_index); ret = xhci_configure_endpoint(xhci, urb->dev, command, true, false); /* Clean up the input context for later use by bandwidth * functions. */ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); command_cleanup: kfree(command->completion); kfree(command); } return ret; }
/* Setup an xHCI virtual device for a Set Address command */ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev) { struct xhci_virt_device *dev; struct xhci_ep_ctx *ep0_ctx; struct usb_device *top_dev; struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; dev = xhci->devs[udev->slot_id]; /* Slot ID 0 is reserved */ if (udev->slot_id == 0 || !dev) { xhci_warn(xhci, "Slot ID %d is not assigned to this device\n", udev->slot_id); return -EINVAL; } ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0); ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx); slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx); /* 2) New slot context and endpoint 0 context are valid*/ ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG; /* 3) Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= LAST_CTX(1); slot_ctx->dev_info |= (u32) udev->route; switch (udev->speed) { case USB_SPEED_SUPER: slot_ctx->dev_info |= (u32) SLOT_SPEED_SS; break; case USB_SPEED_HIGH: slot_ctx->dev_info |= (u32) SLOT_SPEED_HS; break; case USB_SPEED_FULL: slot_ctx->dev_info |= (u32) SLOT_SPEED_FS; break; case USB_SPEED_LOW: slot_ctx->dev_info |= (u32) SLOT_SPEED_LS; break; case USB_SPEED_WIRELESS: xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); return -EINVAL; break; default: /* Speed was set earlier, this shouldn't happen. */ BUG(); } /* Find the root hub port this device is under */ for (top_dev = udev; top_dev->parent && top_dev->parent->parent; top_dev = top_dev->parent) /* Found device below root hub */; slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum); xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum); /* Is this a LS/FS device under a HS hub? */ if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) && udev->tt) { slot_ctx->tt_info = udev->tt->hub->slot_id; slot_ctx->tt_info |= udev->ttport << 8; if (udev->tt->multi) slot_ctx->dev_info |= DEV_MTT; } xhci_dbg(xhci, "udev->tt = %p\n", udev->tt); xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport); /* Step 4 - ring already allocated */ /* Step 5 */ ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP); /* * XXX: Not sure about wireless USB devices. */ switch (udev->speed) { case USB_SPEED_SUPER: ep0_ctx->ep_info2 |= MAX_PACKET(512); break; case USB_SPEED_HIGH: /* USB core guesses at a 64-byte max packet first for FS devices */ case USB_SPEED_FULL: ep0_ctx->ep_info2 |= MAX_PACKET(64); break; case USB_SPEED_LOW: ep0_ctx->ep_info2 |= MAX_PACKET(8); break; case USB_SPEED_WIRELESS: xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); return -EINVAL; break; default: /* New speed? */ BUG(); } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ ep0_ctx->ep_info2 |= MAX_BURST(0); ep0_ctx->ep_info2 |= ERROR_COUNT(3); ep0_ctx->deq = dev->eps[0].ring->first_seg->dma; ep0_ctx->deq |= dev->eps[0].ring->cycle_state; /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ return 0; }
int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep) { struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u32 added_ctxs; unsigned int last_ctx; u32 new_add_flags, new_drop_flags, new_slot_info; int ret = 0; ret = xhci_check_args(hcd, udev, ep, 1, __func__); if (ret <= 0) { ep->hcpriv = NULL; return ret; } xhci = hcd_to_xhci(hcd); added_ctxs = xhci_get_endpoint_flag(&ep->desc); last_ctx = xhci_last_valid_endpoint(added_ctxs); if (added_ctxs == SLOT_FLAG || added_ctxs == EP0_FLAG) { xhci_dbg(xhci, "xHCI %s - can't add slot or ep 0 %#x\n", __func__, added_ctxs); return 0; } if (!xhci->devs || !xhci->devs[udev->slot_id]) { xhci_warn(xhci, "xHCI %s called with unaddressed device\n", __func__); return -EINVAL; } in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) { xhci_warn(xhci, "xHCI %s called with enabled ep %p\n", __func__, ep); return 0; } if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], udev, ep, GFP_KERNEL) < 0) { dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", __func__, ep->desc.bEndpointAddress); return -ENOMEM; } ctrl_ctx->add_flags |= added_ctxs; new_add_flags = ctrl_ctx->add_flags; new_drop_flags = ctrl_ctx->drop_flags; slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) { slot_ctx->dev_info &= ~LAST_CTX_MASK; slot_ctx->dev_info |= LAST_CTX(last_ctx); } new_slot_info = slot_ctx->dev_info; ep->hcpriv = udev; xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n", (unsigned int) ep->desc.bEndpointAddress, udev->slot_id, (unsigned int) new_drop_flags, (unsigned int) new_add_flags, (unsigned int) new_slot_info); return 0; }
int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep) { struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; struct xhci_input_control_ctx *ctrl_ctx; struct xhci_slot_ctx *slot_ctx; unsigned int last_ctx; unsigned int ep_index; struct xhci_ep_ctx *ep_ctx; u32 drop_flag; u32 new_add_flags, new_drop_flags, new_slot_info; int ret; ret = xhci_check_args(hcd, udev, ep, 1, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); drop_flag = xhci_get_endpoint_flag(&ep->desc); if (drop_flag == SLOT_FLAG || drop_flag == EP0_FLAG) { xhci_dbg(xhci, "xHCI %s - can't drop slot or ep 0 %#x\n", __func__, drop_flag); return 0; } if (!xhci->devs || !xhci->devs[udev->slot_id]) { xhci_warn(xhci, "xHCI %s called with unaddressed device\n", __func__); return -EINVAL; } in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED || ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) { xhci_warn(xhci, "xHCI %s called with disabled ep %p\n", __func__, ep); return 0; } ctrl_ctx->drop_flags |= drop_flag; new_drop_flags = ctrl_ctx->drop_flags; ctrl_ctx->add_flags &= ~drop_flag; new_add_flags = ctrl_ctx->add_flags; last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) { slot_ctx->dev_info &= ~LAST_CTX_MASK; slot_ctx->dev_info |= LAST_CTX(last_ctx); } new_slot_info = slot_ctx->dev_info; xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep); xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n", (unsigned int) ep->desc.bEndpointAddress, udev->slot_id, (unsigned int) new_drop_flags, (unsigned int) new_add_flags, (unsigned int) new_slot_info); return 0; }
int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_device *vdev; struct xhci_command *config_cmd; struct xhci_input_control_ctx *ctrl_ctx; struct xhci_slot_ctx *slot_ctx; unsigned long flags; unsigned think_time; int ret; if (!hdev->parent) return 0; vdev = xhci->devs[hdev->slot_id]; if (!vdev) { xhci_warn(xhci, "Cannot update hub desc for unknown device.\n"); return -EINVAL; } config_cmd = xhci_alloc_command(xhci, true, mem_flags); if (!config_cmd) { xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); return -ENOMEM; } spin_lock_irqsave(&xhci->lock, flags); xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx); ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx); ctrl_ctx->add_flags |= SLOT_FLAG; slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); slot_ctx->dev_info |= DEV_HUB; if (tt->multi) slot_ctx->dev_info |= DEV_MTT; if (xhci->hci_version > 0x95) { xhci_dbg(xhci, "xHCI version %x needs hub " "TT think time and number of ports\n", (unsigned int) xhci->hci_version); slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild); think_time = tt->think_time; if (think_time != 0) think_time = (think_time / 666) - 1; slot_ctx->tt_info |= TT_THINK_TIME(think_time); } else { xhci_dbg(xhci, "xHCI version %x doesn't need hub " "TT think time or number of ports\n", (unsigned int) xhci->hci_version); } slot_ctx->dev_state = 0; spin_unlock_irqrestore(&xhci->lock, flags); xhci_dbg(xhci, "Set up %s for hub device.\n", (xhci->hci_version > 0x95) ? "configure endpoint" : "evaluate context"); xhci_dbg(xhci, "Slot %u Input Context:\n", hdev->slot_id); xhci_dbg_ctx(xhci, config_cmd->in_ctx, 0); if (xhci->hci_version > 0x95) ret = xhci_configure_endpoint(xhci, hdev, config_cmd, false, false); else ret = xhci_configure_endpoint(xhci, hdev, config_cmd, true, false); xhci_dbg(xhci, "Slot %u Output Context:\n", hdev->slot_id); xhci_dbg_ctx(xhci, vdev->out_ctx, 0); xhci_free_command(xhci, config_cmd); return ret; }
int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) { unsigned long flags; int timeleft; struct xhci_virt_device *virt_dev; int ret = 0; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); return -EINVAL; } virt_dev = xhci->devs[udev->slot_id]; if (!udev->config) xhci_setup_addressable_virt_dev(xhci, udev); xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); return ret; } xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, USB_CTRL_SET_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for a slot\n", timeleft == 0 ? "Timeout" : "Signal"); return -ETIME; } switch (virt_dev->cmd_status) { case COMP_CTX_STATE: case COMP_EBADSLT: xhci_err(xhci, "Setup ERROR: address device command for slot %d.\n", udev->slot_id); ret = -EINVAL; break; case COMP_TX_ERR: dev_warn(&udev->dev, "Device not responding to set address.\n"); ret = -EPROTO; break; case COMP_SUCCESS: xhci_dbg(xhci, "Successful Address Device command\n"); break; default: xhci_err(xhci, "ERROR: unexpected command completion " "code 0x%x.\n", virt_dev->cmd_status); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); ret = -EINVAL; break; } if (ret) { return ret; } temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64); xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n", udev->slot_id, &xhci->dcbaa->dev_context_ptrs[udev->slot_id], (unsigned long long) xhci->dcbaa->dev_context_ptrs[udev->slot_id]); xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", (unsigned long long)virt_dev->out_ctx->dma); xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1; ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx->add_flags = 0; ctrl_ctx->drop_flags = 0; xhci_dbg(xhci, "Device address = %d\n", udev->devnum); set_bit(udev->devnum, udev->bus->devmap.devicemap); return 0; }