diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2010-07-30 01:12:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:44 -0400 |
commit | 021bff9179c2d19c26599dc3e9134d04cf1c8a3a (patch) | |
tree | 99c7dba0d83e607a2ca9d12e50bd8ee7bad56181 /drivers/usb | |
parent | c6ba1c2af2da31ffb57949edbd1dba34f97d1d4b (diff) |
USB: xhci: Performance - move functions that find ep ring.
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 43 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 44 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 41 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 5 |
4 files changed, 85 insertions, 48 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 7d60d1f4debb..ac57f538f957 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -391,49 +391,6 @@ struct xhci_ring *xhci_stream_id_to_ring( | |||
391 | return ep->stream_info->stream_rings[stream_id]; | 391 | return ep->stream_info->stream_rings[stream_id]; |
392 | } | 392 | } |
393 | 393 | ||
394 | struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
395 | unsigned int slot_id, unsigned int ep_index, | ||
396 | unsigned int stream_id) | ||
397 | { | ||
398 | struct xhci_virt_ep *ep; | ||
399 | |||
400 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
401 | /* Common case: no streams */ | ||
402 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
403 | return ep->ring; | ||
404 | |||
405 | if (stream_id == 0) { | ||
406 | xhci_warn(xhci, | ||
407 | "WARN: Slot ID %u, ep index %u has streams, " | ||
408 | "but URB has no stream ID.\n", | ||
409 | slot_id, ep_index); | ||
410 | return NULL; | ||
411 | } | ||
412 | |||
413 | if (stream_id < ep->stream_info->num_streams) | ||
414 | return ep->stream_info->stream_rings[stream_id]; | ||
415 | |||
416 | xhci_warn(xhci, | ||
417 | "WARN: Slot ID %u, ep index %u has " | ||
418 | "stream IDs 1 to %u allocated, " | ||
419 | "but stream ID %u is requested.\n", | ||
420 | slot_id, ep_index, | ||
421 | ep->stream_info->num_streams - 1, | ||
422 | stream_id); | ||
423 | return NULL; | ||
424 | } | ||
425 | |||
426 | /* Get the right ring for the given URB. | ||
427 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
428 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
429 | */ | ||
430 | struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
431 | struct urb *urb) | ||
432 | { | ||
433 | return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, | ||
434 | xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); | ||
435 | } | ||
436 | |||
437 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 394 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
438 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, | 395 | static int xhci_test_radix_tree(struct xhci_hcd *xhci, |
439 | unsigned int num_streams, | 396 | unsigned int num_streams, |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index da3519e76e2b..7f1c54585b63 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -419,6 +419,50 @@ static struct xhci_segment *find_trb_seg( | |||
419 | return cur_seg; | 419 | return cur_seg; |
420 | } | 420 | } |
421 | 421 | ||
422 | |||
423 | static struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
424 | unsigned int slot_id, unsigned int ep_index, | ||
425 | unsigned int stream_id) | ||
426 | { | ||
427 | struct xhci_virt_ep *ep; | ||
428 | |||
429 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
430 | /* Common case: no streams */ | ||
431 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
432 | return ep->ring; | ||
433 | |||
434 | if (stream_id == 0) { | ||
435 | xhci_warn(xhci, | ||
436 | "WARN: Slot ID %u, ep index %u has streams, " | ||
437 | "but URB has no stream ID.\n", | ||
438 | slot_id, ep_index); | ||
439 | return NULL; | ||
440 | } | ||
441 | |||
442 | if (stream_id < ep->stream_info->num_streams) | ||
443 | return ep->stream_info->stream_rings[stream_id]; | ||
444 | |||
445 | xhci_warn(xhci, | ||
446 | "WARN: Slot ID %u, ep index %u has " | ||
447 | "stream IDs 1 to %u allocated, " | ||
448 | "but stream ID %u is requested.\n", | ||
449 | slot_id, ep_index, | ||
450 | ep->stream_info->num_streams - 1, | ||
451 | stream_id); | ||
452 | return NULL; | ||
453 | } | ||
454 | |||
455 | /* Get the right ring for the given URB. | ||
456 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
457 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
458 | */ | ||
459 | static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
460 | struct urb *urb) | ||
461 | { | ||
462 | return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, | ||
463 | xhci_get_endpoint_index(&urb->ep->desc), urb->stream_id); | ||
464 | } | ||
465 | |||
422 | /* | 466 | /* |
423 | * Move the xHC's endpoint ring dequeue pointer past cur_td. | 467 | * Move the xHC's endpoint ring dequeue pointer past cur_td. |
424 | * Record the new state of the xHC's endpoint ring dequeue segment, | 468 | * Record the new state of the xHC's endpoint ring dequeue segment, |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 89ac48534099..f5e0b00cbb83 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -916,6 +916,47 @@ dying: | |||
916 | return -ESHUTDOWN; | 916 | return -ESHUTDOWN; |
917 | } | 917 | } |
918 | 918 | ||
919 | /* Get the right ring for the given URB. | ||
920 | * If the endpoint supports streams, boundary check the URB's stream ID. | ||
921 | * If the endpoint doesn't support streams, return the singular endpoint ring. | ||
922 | */ | ||
923 | static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
924 | struct urb *urb) | ||
925 | { | ||
926 | unsigned int slot_id; | ||
927 | unsigned int ep_index; | ||
928 | unsigned int stream_id; | ||
929 | struct xhci_virt_ep *ep; | ||
930 | |||
931 | slot_id = urb->dev->slot_id; | ||
932 | ep_index = xhci_get_endpoint_index(&urb->ep->desc); | ||
933 | stream_id = urb->stream_id; | ||
934 | ep = &xhci->devs[slot_id]->eps[ep_index]; | ||
935 | /* Common case: no streams */ | ||
936 | if (!(ep->ep_state & EP_HAS_STREAMS)) | ||
937 | return ep->ring; | ||
938 | |||
939 | if (stream_id == 0) { | ||
940 | xhci_warn(xhci, | ||
941 | "WARN: Slot ID %u, ep index %u has streams, " | ||
942 | "but URB has no stream ID.\n", | ||
943 | slot_id, ep_index); | ||
944 | return NULL; | ||
945 | } | ||
946 | |||
947 | if (stream_id < ep->stream_info->num_streams) | ||
948 | return ep->stream_info->stream_rings[stream_id]; | ||
949 | |||
950 | xhci_warn(xhci, | ||
951 | "WARN: Slot ID %u, ep index %u has " | ||
952 | "stream IDs 1 to %u allocated, " | ||
953 | "but stream ID %u is requested.\n", | ||
954 | slot_id, ep_index, | ||
955 | ep->stream_info->num_streams - 1, | ||
956 | stream_id); | ||
957 | return NULL; | ||
958 | } | ||
959 | |||
919 | /* | 960 | /* |
920 | * Remove the URB's TD from the endpoint ring. This may cause the HC to stop | 961 | * Remove the URB's TD from the endpoint ring. This may cause the HC to stop |
921 | * USB transfers, potentially stopping in the middle of a TRB buffer. The HC | 962 | * USB transfers, potentially stopping in the middle of a TRB buffer. The HC |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e1383d91468b..9fe95c4e2a56 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1344,11 +1344,6 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci, | |||
1344 | struct xhci_ring *xhci_dma_to_transfer_ring( | 1344 | struct xhci_ring *xhci_dma_to_transfer_ring( |
1345 | struct xhci_virt_ep *ep, | 1345 | struct xhci_virt_ep *ep, |
1346 | u64 address); | 1346 | u64 address); |
1347 | struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | ||
1348 | struct urb *urb); | ||
1349 | struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, | ||
1350 | unsigned int slot_id, unsigned int ep_index, | ||
1351 | unsigned int stream_id); | ||
1352 | struct xhci_ring *xhci_stream_id_to_ring( | 1347 | struct xhci_ring *xhci_stream_id_to_ring( |
1353 | struct xhci_virt_device *dev, | 1348 | struct xhci_virt_device *dev, |
1354 | unsigned int ep_index, | 1349 | unsigned int ep_index, |