/** * Copy output xhci_slot_ctx to the input xhci_slot_ctx. * Useful when you want to change one particular aspect of the endpoint * and then issue a configure endpoint command. * Only the context entries field matters, but * we'll copy the whole thing anyway. * * @param ctrl Host controller data structure * @param in_ctx contains the inpout context * @param out_ctx contains the inpout context * @return none */ void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *in_ctx, struct xhci_container_ctx *out_ctx) { struct xhci_slot_ctx *in_slot_ctx; struct xhci_slot_ctx *out_slot_ctx; in_slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); out_slot_ctx = xhci_get_slot_ctx(ctrl, out_ctx); in_slot_ctx->dev_info = out_slot_ctx->dev_info; in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2; in_slot_ctx->tt_info = out_slot_ctx->tt_info; in_slot_ctx->dev_state = out_slot_ctx->dev_state; }
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); }
static int xhci_slot_context_show(struct seq_file *s, void *unused) { struct xhci_hcd *xhci; struct xhci_slot_ctx *slot_ctx; struct xhci_slot_priv *priv = s->private; struct xhci_virt_device *dev = priv->dev; xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus)); slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma, xhci_decode_slot_context(slot_ctx->dev_info, slot_ctx->dev_info2, slot_ctx->tt_info, slot_ctx->dev_state)); return 0; }
char *xhci_get_slot_state(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) { struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); switch (GET_SLOT_STATE(slot_ctx->dev_state)) { case 0: return "enabled/disabled"; case 1: return "default"; case 2: return "addressed"; case 3: return "configured"; default: return "reserved"; } }
char *xhci_get_slot_state(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) { struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) { case SLOT_STATE_ENABLED: return "enabled/disabled"; case SLOT_STATE_DEFAULT: return "default"; case SLOT_STATE_ADDRESSED: return "addressed"; case SLOT_STATE_CONFIGURED: return "configured"; default: return "reserved"; } }
static void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) { /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; int i; struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx->bytes); int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); xhci_dbg(xhci, "Slot Context:\n"); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n", &slot_ctx->dev_info, (unsigned long long)dma, slot_ctx->dev_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", &slot_ctx->dev_info2, (unsigned long long)dma, slot_ctx->dev_info2); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", &slot_ctx->tt_info, (unsigned long long)dma, slot_ctx->tt_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", &slot_ctx->dev_state, (unsigned long long)dma, slot_ctx->dev_state); dma += field_size; for (i = 0; i < 4; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &slot_ctx->reserved[i], (unsigned long long)dma, slot_ctx->reserved[i], i); dma += field_size; } if (csz) dbg_rsvd64(xhci, (u64 *)slot_ctx, dma); }
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; } }
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); 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); } slot_ctx = xhci_get_slot_ctx(xhci, ctx); xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); }
/** * Setup an xHCI virtual device for a Set Address command * * @param udev pointer to the Device Data Structure * @return returns negative value on failure else 0 on success */ void xhci_setup_addressable_virt_dev(struct usb_device *udev) { struct usb_device *hop = udev; struct xhci_virt_device *virt_dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; u32 port_num = 0; u64 trb_64 = 0; struct xhci_ctrl *ctrl = udev->controller; virt_dev = ctrl->devs[udev->slot_id]; BUG_ON(!virt_dev); /* Extract the EP0 and Slot Ctrl */ ep0_ctx = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, 0); slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); /* Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | 0); switch (udev->speed) { case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); break; case USB_SPEED_HIGH: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); break; case USB_SPEED_FULL: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); break; case USB_SPEED_LOW: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); break; default: /* Speed was set earlier, this shouldn't happen. */ BUG(); } /* Extract the root hub port number */ if (hop->parent) while (hop->parent->parent) hop = hop->parent; port_num = hop->portnr; debug("port_num = %d\n", port_num); slot_ctx->dev_info2 |= cpu_to_le32(((port_num & ROOT_HUB_PORT_MASK) << ROOT_HUB_PORT_SHIFT)); /* Step 4 - ring already allocated */ /* Step 5 */ ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); debug("SPEED = %d\n", udev->speed); switch (udev->speed) { case USB_SPEED_SUPER: ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 512bytes\n"); 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 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 64bytes\n"); break; case USB_SPEED_LOW: ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 8bytes\n"); break; default: /* New speed? */ BUG(); } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ ep0_ctx->ep_info2 |= cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ xhci_flush_cache((uint32_t)ep0_ctx, sizeof(struct xhci_ep_ctx)); xhci_flush_cache((uint32_t)slot_ctx, sizeof(struct xhci_slot_ctx)); }
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; }
/** * Setup an xHCI virtual device for a Set Address command * * @param udev pointer to the Device Data Structure * @return returns negative value on failure else 0 on success */ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, struct usb_device *udev, int hop_portnr) { struct xhci_virt_device *virt_dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; u32 port_num = 0; u64 trb_64 = 0; int slot_id = udev->slot_id; int speed = udev->speed; int route = 0; #if CONFIG_IS_ENABLED(DM_USB) struct usb_device *dev = udev; struct usb_hub_device *hub; #endif virt_dev = ctrl->devs[slot_id]; BUG_ON(!virt_dev); /* Extract the EP0 and Slot Ctrl */ ep0_ctx = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, 0); slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); /* Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1)); #if CONFIG_IS_ENABLED(DM_USB) /* Calculate the route string for this device */ port_num = dev->portnr; while (!usb_hub_is_root_hub(dev->dev)) { hub = dev_get_uclass_priv(dev->dev); /* * Each hub in the topology is expected to have no more than * 15 ports in order for the route string of a device to be * unique. SuperSpeed hubs are restricted to only having 15 * ports, but FS/LS/HS hubs are not. The xHCI specification * says that if the port number the device is greater than 15, * that portion of the route string shall be set to 15. */ if (port_num > 15) port_num = 15; route |= port_num << (hub->hub_depth * 4); dev = dev_get_parent_priv(dev->dev); port_num = dev->portnr; dev = dev_get_parent_priv(dev->dev->parent); } debug("route string %x\n", route); #endif slot_ctx->dev_info |= route; switch (speed) { case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); break; case USB_SPEED_HIGH: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); break; case USB_SPEED_FULL: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); break; case USB_SPEED_LOW: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); break; default: /* Speed was set earlier, this shouldn't happen. */ BUG(); } #if CONFIG_IS_ENABLED(DM_USB) /* Set up TT fields to support FS/LS devices */ if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) { struct udevice *parent = udev->dev; dev = udev; do { port_num = dev->portnr; dev = dev_get_parent_priv(parent); if (usb_hub_is_root_hub(dev->dev)) break; parent = dev->dev->parent; } while (dev->speed != USB_SPEED_HIGH); if (!usb_hub_is_root_hub(dev->dev)) { hub = dev_get_uclass_priv(dev->dev); if (hub->tt.multi) slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); slot_ctx->tt_info |= cpu_to_le32(TT_PORT(port_num)); slot_ctx->tt_info |= cpu_to_le32(TT_SLOT(dev->slot_id)); } } #endif port_num = hop_portnr; debug("port_num = %d\n", port_num); slot_ctx->dev_info2 |= cpu_to_le32(((port_num & ROOT_HUB_PORT_MASK) << ROOT_HUB_PORT_SHIFT)); /* Step 4 - ring already allocated */ /* Step 5 */ ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); debug("SPEED = %d\n", speed); switch (speed) { case USB_SPEED_SUPER: ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 512bytes\n"); 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 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 64bytes\n"); break; case USB_SPEED_LOW: ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 8bytes\n"); break; default: /* New speed? */ BUG(); } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ ep0_ctx->ep_info2 |= cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* * xHCI spec 6.2.3: * software shall set 'Average TRB Length' to 8 for control endpoints. */ ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8)); /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx)); xhci_flush_cache((uintptr_t)slot_ctx, sizeof(struct xhci_slot_ctx)); }
/* 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; }
void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) { /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; int i; struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx->bytes); int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); xhci_dbg(xhci, "Slot Context:\n"); #if 0 /* original code */ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n", &slot_ctx->dev_info, (unsigned long long)dma, slot_ctx->dev_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", &slot_ctx->dev_info2, (unsigned long long)dma, slot_ctx->dev_info2); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", &slot_ctx->tt_info, (unsigned long long)dma, slot_ctx->tt_info); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", &slot_ctx->dev_state, (unsigned long long)dma, slot_ctx->dev_state); dma += field_size; for (i = 0; i < 4; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &slot_ctx->reserved[i], (unsigned long long)dma, slot_ctx->reserved[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 - dev_info\n", &slot_ctx->dev_info, (unsigned long long)dma, xhci_desc_readl(xhci, &slot_ctx->dev_info)); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", &slot_ctx->dev_info2, (unsigned long long)dma, xhci_desc_readl(xhci, &slot_ctx->dev_info2)); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", &slot_ctx->tt_info, (unsigned long long)dma, xhci_desc_readl(xhci, &slot_ctx->tt_info)); dma += field_size; xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", &slot_ctx->dev_state, (unsigned long long)dma, xhci_desc_readl(xhci, &slot_ctx->dev_state)); dma += field_size; for (i = 0; i < 4; ++i) { xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", &slot_ctx->reserved[i], (unsigned long long)dma, xhci_desc_readl(xhci, &slot_ctx->reserved[i]), i); dma += field_size; } #endif if (csz) dbg_rsvd64(xhci, (u64 *)slot_ctx, dma); }