mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-14 04:26:45 +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
4 changed files with 85 additions and 48 deletions
|
@ -391,49 +391,6 @@ struct xhci_ring *xhci_stream_id_to_ring(
|
||||||
return ep->stream_info->stream_rings[stream_id];
|
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
|
#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
|
||||||
static int xhci_test_radix_tree(struct xhci_hcd *xhci,
|
static int xhci_test_radix_tree(struct xhci_hcd *xhci,
|
||||||
unsigned int num_streams,
|
unsigned int num_streams,
|
||||||
|
|
|
@ -419,6 +419,50 @@ static struct xhci_segment *find_trb_seg(
|
||||||
return cur_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.
|
* Move the xHC's endpoint ring dequeue pointer past cur_td.
|
||||||
* Record the new state of the xHC's endpoint ring dequeue segment,
|
* Record the new state of the xHC's endpoint ring dequeue segment,
|
||||||
|
|
|
@ -916,6 +916,47 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
|
||||||
return -ESHUTDOWN;
|
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
|
* 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
|
* 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_ring *xhci_dma_to_transfer_ring(
|
||||||
struct xhci_virt_ep *ep,
|
struct xhci_virt_ep *ep,
|
||||||
u64 address);
|
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_ring *xhci_stream_id_to_ring(
|
||||||
struct xhci_virt_device *dev,
|
struct xhci_virt_device *dev,
|
||||||
unsigned int ep_index,
|
unsigned int ep_index,
|
||||||
|
|
Loading…
Reference in a new issue