|
@@ -722,7 +722,9 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
struct usb_host_endpoint *ep)
|
|
|
{
|
|
|
struct xhci_hcd *xhci;
|
|
|
- struct xhci_device_control *in_ctx;
|
|
|
+ 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;
|
|
@@ -750,31 +752,34 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
}
|
|
|
|
|
|
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->devs[udev->slot_id]->out_ctx->ep[ep_index];
|
|
|
+ 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 & EP_STATE_MASK) == EP_STATE_DISABLED ||
|
|
|
- in_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- in_ctx->drop_flags |= drop_flag;
|
|
|
- new_drop_flags = in_ctx->drop_flags;
|
|
|
+ ctrl_ctx->drop_flags |= drop_flag;
|
|
|
+ new_drop_flags = ctrl_ctx->drop_flags;
|
|
|
|
|
|
- in_ctx->add_flags = ~drop_flag;
|
|
|
- new_add_flags = in_ctx->add_flags;
|
|
|
+ ctrl_ctx->add_flags = ~drop_flag;
|
|
|
+ new_add_flags = ctrl_ctx->add_flags;
|
|
|
|
|
|
- last_ctx = xhci_last_valid_endpoint(in_ctx->add_flags);
|
|
|
+ last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
|
|
|
+ slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
|
|
/* Update the last valid endpoint context, if we deleted the last one */
|
|
|
- if ((in_ctx->slot.dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
|
|
|
- in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
|
|
|
- in_ctx->slot.dev_info |= LAST_CTX(last_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 = in_ctx->slot.dev_info;
|
|
|
+ new_slot_info = slot_ctx->dev_info;
|
|
|
|
|
|
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
|
|
|
|
|
@@ -804,9 +809,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
struct usb_host_endpoint *ep)
|
|
|
{
|
|
|
struct xhci_hcd *xhci;
|
|
|
- struct xhci_device_control *in_ctx;
|
|
|
+ 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;
|
|
@@ -839,12 +846,14 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
}
|
|
|
|
|
|
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->devs[udev->slot_id]->out_ctx->ep[ep_index];
|
|
|
+ ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
|
|
/* If the HCD has already noted the endpoint is enabled,
|
|
|
* ignore this request.
|
|
|
*/
|
|
|
- if (in_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
|
|
+ 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;
|
|
@@ -862,8 +871,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- in_ctx->add_flags |= added_ctxs;
|
|
|
- new_add_flags = in_ctx->add_flags;
|
|
|
+ ctrl_ctx->add_flags |= added_ctxs;
|
|
|
+ new_add_flags = ctrl_ctx->add_flags;
|
|
|
|
|
|
/* If xhci_endpoint_disable() was called for this endpoint, but the
|
|
|
* xHC hasn't been notified yet through the check_bandwidth() call,
|
|
@@ -871,14 +880,15 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
* descriptors. We must drop and re-add this endpoint, so we leave the
|
|
|
* drop flags alone.
|
|
|
*/
|
|
|
- new_drop_flags = in_ctx->drop_flags;
|
|
|
+ new_drop_flags = ctrl_ctx->drop_flags;
|
|
|
|
|
|
+ slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
|
|
/* Update the last valid endpoint context, if we just added one past */
|
|
|
- if ((in_ctx->slot.dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
|
|
|
- in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
|
|
|
- in_ctx->slot.dev_info |= LAST_CTX(last_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 = in_ctx->slot.dev_info;
|
|
|
+ new_slot_info = slot_ctx->dev_info;
|
|
|
|
|
|
/* Store the usb_device pointer for later use */
|
|
|
ep->hcpriv = udev;
|
|
@@ -892,9 +902,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
|
|
|
+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;
|
|
|
|
|
|
/* When a device's add flag and drop flag are zero, any subsequent
|
|
@@ -902,13 +914,15 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
|
|
|
* untouched. Make sure we don't leave any old state in the input
|
|
|
* endpoint contexts.
|
|
|
*/
|
|
|
- virt_dev->in_ctx->drop_flags = 0;
|
|
|
- virt_dev->in_ctx->add_flags = 0;
|
|
|
- virt_dev->in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
|
|
|
+ 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;
|
|
|
/* Endpoint 0 is always valid */
|
|
|
- virt_dev->in_ctx->slot.dev_info |= LAST_CTX(1);
|
|
|
+ slot_ctx->dev_info |= LAST_CTX(1);
|
|
|
for (i = 1; i < 31; ++i) {
|
|
|
- ep_ctx = &virt_dev->in_ctx->ep[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;
|
|
@@ -934,6 +948,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
unsigned long flags;
|
|
|
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)
|
|
@@ -949,16 +965,18 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
virt_dev = xhci->devs[udev->slot_id];
|
|
|
|
|
|
/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
|
|
|
- virt_dev->in_ctx->add_flags |= SLOT_FLAG;
|
|
|
- virt_dev->in_ctx->add_flags &= ~EP0_FLAG;
|
|
|
- virt_dev->in_ctx->drop_flags &= ~SLOT_FLAG;
|
|
|
- virt_dev->in_ctx->drop_flags &= ~EP0_FLAG;
|
|
|
+ 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");
|
|
|
- xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma,
|
|
|
- LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
|
|
|
+ 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));
|
|
|
|
|
|
spin_lock_irqsave(&xhci->lock, flags);
|
|
|
- ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx_dma,
|
|
|
+ ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
|
|
|
udev->slot_id);
|
|
|
if (ret < 0) {
|
|
|
spin_unlock_irqrestore(&xhci->lock, flags);
|
|
@@ -1013,10 +1031,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
}
|
|
|
|
|
|
xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
|
|
|
- xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma,
|
|
|
- LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
|
|
|
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx,
|
|
|
+ LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
|
|
|
|
|
- xhci_zero_in_ctx(virt_dev);
|
|
|
+ xhci_zero_in_ctx(xhci, virt_dev);
|
|
|
/* Free any old rings */
|
|
|
for (i = 1; i < 31; ++i) {
|
|
|
if (virt_dev->new_ep_rings[i]) {
|
|
@@ -1054,7 +1072,7 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
virt_dev->new_ep_rings[i] = NULL;
|
|
|
}
|
|
|
}
|
|
|
- xhci_zero_in_ctx(virt_dev);
|
|
|
+ xhci_zero_in_ctx(xhci, virt_dev);
|
|
|
}
|
|
|
|
|
|
/* Deal with stalled endpoints. The core should have sent the control message
|
|
@@ -1187,6 +1205,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
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) {
|
|
@@ -1201,11 +1221,11 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
xhci_setup_addressable_virt_dev(xhci, udev);
|
|
|
/* Otherwise, assume the core has the device configured how it wants */
|
|
|
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
|
|
- xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
|
|
|
+ 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);
|
|
|
+ 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");
|
|
@@ -1246,7 +1266,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
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, virt_dev->out_ctx_dma, 2);
|
|
|
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
|
|
|
ret = -EINVAL;
|
|
|
break;
|
|
|
}
|
|
@@ -1261,19 +1281,21 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
(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);
|
|
|
+ (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, virt_dev->in_ctx_dma, 2);
|
|
|
+ xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
|
|
|
xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
|
|
|
- xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
|
|
|
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
|
|
|
/*
|
|
|
* USB core uses address 1 for the roothubs, so we add one to the
|
|
|
* address given back to us by the HC.
|
|
|
*/
|
|
|
- udev->devnum = (virt_dev->out_ctx->slot.dev_state & DEV_ADDR_MASK) + 1;
|
|
|
+ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
|
|
|
+ udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
|
|
|
/* Zero the input context control for later use */
|
|
|
- virt_dev->in_ctx->add_flags = 0;
|
|
|
- virt_dev->in_ctx->drop_flags = 0;
|
|
|
+ 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);
|
|
|
/* XXX Meh, not sure if anyone else but choose_address uses this. */
|
|
@@ -1315,7 +1337,6 @@ static int __init xhci_hcd_init(void)
|
|
|
/* xhci_device_control has eight fields, and also
|
|
|
* embeds one xhci_slot_ctx and 31 xhci_ep_ctx
|
|
|
*/
|
|
|
- BUILD_BUG_ON(sizeof(struct xhci_device_control) != (8+8+8*31)*32/8);
|
|
|
BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
|
|
|
BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
|
|
|
BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
|