]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/usb/host/xhci-mem.c
USB: xHCI: bus power management implementation
[mv-sheeva.git] / drivers / usb / host / xhci-mem.c
index 2eb658d2639477bccb3051804fb6364dc79e29c0..202770676da30c409652dc1aca0b4d33a857d366 100644 (file)
@@ -391,49 +391,6 @@ struct xhci_ring *xhci_stream_id_to_ring(
        return ep->stream_info->stream_rings[stream_id];
 }
 
-struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci,
-               unsigned int slot_id, unsigned int ep_index,
-               unsigned int stream_id)
-{
-       struct xhci_virt_ep *ep;
-
-       ep = &xhci->devs[slot_id]->eps[ep_index];
-       /* Common case: no streams */
-       if (!(ep->ep_state & EP_HAS_STREAMS))
-               return ep->ring;
-
-       if (stream_id == 0) {
-               xhci_warn(xhci,
-                               "WARN: Slot ID %u, ep index %u has streams, "
-                               "but URB has no stream ID.\n",
-                               slot_id, ep_index);
-               return NULL;
-       }
-
-       if (stream_id < ep->stream_info->num_streams)
-               return ep->stream_info->stream_rings[stream_id];
-
-       xhci_warn(xhci,
-                       "WARN: Slot ID %u, ep index %u has "
-                       "stream IDs 1 to %u allocated, "
-                       "but stream ID %u is requested.\n",
-                       slot_id, ep_index,
-                       ep->stream_info->num_streams - 1,
-                       stream_id);
-       return NULL;
-}
-
-/* Get the right ring for the given URB.
- * If the endpoint supports streams, boundary check the URB's stream ID.
- * If the endpoint doesn't support streams, return the singular endpoint ring.
- */
-struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
-               struct urb *urb)
-{
-       return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id,
-               xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id);
-}
-
 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
 static int xhci_test_radix_tree(struct xhci_hcd *xhci,
                unsigned int num_streams,
@@ -821,6 +778,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 
        init_completion(&dev->cmd_completion);
        INIT_LIST_HEAD(&dev->cmd_list);
+       dev->udev = udev;
 
        /* Point to output device context in dcbaa. */
        xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
@@ -909,6 +867,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
                        top_dev = top_dev->parent)
                /* Found device below root hub */;
        slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
+       dev->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? */
@@ -1112,8 +1071,18 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        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);
+       /*
+        * Isochronous endpoint ring needs bigger size because one isoc URB
+        * carries multiple packets and it will insert multiple tds to the
+        * ring.
+        * This should be replaced with dynamic ring resizing in the future.
+        */
+       if (usb_endpoint_xfer_isoc(&ep->desc))
+               virt_dev->eps[ep_index].new_ring =
+                       xhci_ring_alloc(xhci, 8, true, mem_flags);
+       else
+               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)
@@ -1124,6 +1093,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
                virt_dev->num_rings_cached--;
                xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring);
        }
+       virt_dev->eps[ep_index].skip = false;
        ep_ring = virt_dev->eps[ep_index].new_ring;
        ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
 
@@ -1389,6 +1359,22 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
        return command;
 }
 
+void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv)
+{
+       int last;
+
+       if (!urb_priv)
+               return;
+
+       last = urb_priv->length - 1;
+       if (last >= 0) {
+               int     i;
+               for (i = 0; i <= last; i++)
+                       kfree(urb_priv->td[i]);
+       }
+       kfree(urb_priv);
+}
+
 void xhci_free_command(struct xhci_hcd *xhci,
                struct xhci_command *command)
 {
@@ -1459,6 +1445,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        scratchpad_free(xhci);
        xhci->page_size = 0;
        xhci->page_shift = 0;
+       xhci->bus_suspended = 0;
 }
 
 static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@@ -1588,7 +1575,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags)
        unsigned int num_tests;
        int i, ret;
 
-       num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]);
+       num_tests = ARRAY_SIZE(simple_test_vector);
        for (i = 0; i < num_tests; i++) {
                ret = xhci_test_trb_in_td(xhci,
                                xhci->event_ring->first_seg,
@@ -1601,7 +1588,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags)
                        return ret;
        }
 
-       num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]);
+       num_tests = ARRAY_SIZE(complex_test_vector);
        for (i = 0; i < num_tests; i++) {
                ret = xhci_test_trb_in_td(xhci,
                                complex_test_vector[i].input_seg,
@@ -1617,6 +1604,29 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags)
        return 0;
 }
 
+static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
+{
+       u64 temp;
+       dma_addr_t deq;
+
+       deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
+                       xhci->event_ring->dequeue);
+       if (deq == 0 && !in_interrupt())
+               xhci_warn(xhci, "WARN something wrong with SW event ring "
+                               "dequeue ptr.\n");
+       /* Update HC event ring dequeue pointer */
+       temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+       temp &= ERST_PTR_MASK;
+       /* Don't clear the EHB bit (which is RW1C) because
+        * there might be more events to service.
+        */
+       temp &= ~ERST_EHB;
+       xhci_dbg(xhci, "// Write event ring dequeue pointer, "
+                       "preserving EHB bit\n");
+       xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+                       &xhci->ir_set->erst_dequeue);
+}
+
 
 int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 {
@@ -1794,6 +1804,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        init_completion(&xhci->addr_dev);
        for (i = 0; i < MAX_HC_SLOTS; ++i)
                xhci->devs[i] = NULL;
+       for (i = 0; i < MAX_HC_PORTS; ++i)
+               xhci->resume_done[i] = 0;
 
        if (scratchpad_alloc(xhci, flags))
                goto fail;