USB: xhci: Performance - move functions that find ep ring.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Fri, 30 Jul 2010 05:12:20 +0000 (22:12 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 Aug 2010 21:35:44 +0000 (14:35 -0700)
I've been using perf to measure the top symbols while transferring 1GB of data
on a USB 3.0 drive with dd.  This is using the raw disk with /dev/sdb, with a
block size of 1K.

During performance testing, the top symbol was xhci_triad_to_transfer_ring(), a
function that should return immediately if streams are not enabled for an
endpoint.  It turned out that the functions to find the endpoint ring was
defined in xhci-mem.c and used in xhci-ring.c and xhci-hcd.c.  I moved a copy of
xhci_triad_to_transfer_ring() and xhci_urb_to_transfer_ring() into xhci-ring.c
and declared them static.  I also made a static version of
xhci_urb_to_transfer_ring() in xhci.c.

This improved throughput on a 1GB read of the raw disk with dd from
186MB/s to 195MB/s, and perf reported sampling the xhci_triad_to_transfer_ring()
0.06% of the time, rather than 9.26% of the time.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index 7d60d1f4debb328221a1239eadbd580691a8c38e..ac57f538f95772d23739edbef2c52f01694283cd 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,
index da3519e76e2bb990937008c38f5ed5b12eec2e48..7f1c54585b63747ffb0322ea16ac84f30ca464d5 100644 (file)
@@ -419,6 +419,50 @@ static struct xhci_segment *find_trb_seg(
        return cur_seg;
 }
 
+
+static 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.
+ */
+static 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);
+}
+
 /*
  * Move the xHC's endpoint ring dequeue pointer past cur_td.
  * Record the new state of the xHC's endpoint ring dequeue segment,
index 89ac48534099bc36dc76fcdb51463abaf5ecac0d..f5e0b00cbb8375eeb6cf8d62c404b2456912e129 100644 (file)
@@ -916,6 +916,47 @@ dying:
        return -ESHUTDOWN;
 }
 
+/* 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.
+ */
+static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
+               struct urb *urb)
+{
+       unsigned int slot_id;
+       unsigned int ep_index;
+       unsigned int stream_id;
+       struct xhci_virt_ep *ep;
+
+       slot_id = urb->dev->slot_id;
+       ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+       stream_id = urb->stream_id;
+       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;
+}
+
 /*
  * Remove the URB's TD from the endpoint ring.  This may cause the HC to stop
  * USB transfers, potentially stopping in the middle of a TRB buffer.  The HC
index e1383d91468beda0232cdaad92bf3394c72a5338..9fe95c4e2a56751f415498412114f1d3a7ec9d69 100644 (file)
@@ -1344,11 +1344,6 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
 struct xhci_ring *xhci_dma_to_transfer_ring(
                struct xhci_virt_ep *ep,
                u64 address);
-struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
-               struct urb *urb);
-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_ring *xhci_stream_id_to_ring(
                struct xhci_virt_device *dev,
                unsigned int ep_index,