mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-20 00:11:22 +00:00
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>
This commit is contained in:
parent
c6ba1c2af2
commit
021bff9179
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user