summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 27d690d..cc59632 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3123,6 +3123,27 @@ static int count_isoc_trbs_needed(struct xhci_hcd *xhci,
return num_trbs;
}
+/*
+ * The transfer burst count field of the isochronous TRB defines the number of
+ * bursts that are required to move all packets in this TD. Only SuperSpeed
+ * devices can burst up to bMaxBurst number of packets per service interval.
+ * This field is zero based, meaning a value of zero in the field means one
+ * burst. Basically, for everything but SuperSpeed devices, this field will be
+ * zero. Only xHCI 1.0 host controllers support this field.
+ */
+static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci,
+ struct usb_device *udev,
+ struct urb *urb, unsigned int total_packet_count)
+{
+ unsigned int max_burst;
+
+ if (xhci->hci_version < 0x100 || udev->speed != USB_SPEED_SUPER)
+ return 0;
+
+ max_burst = urb->ep->ss_ep_comp.bMaxBurst;
+ return roundup(total_packet_count, max_burst + 1) - 1;
+}
+
/* This is for isoc transfer */
static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3164,14 +3185,18 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
/* Queue the first TRB, even if it's zero-length */
for (i = 0; i < num_tds; i++) {
unsigned int total_packet_count;
+ unsigned int burst_count;
first_trb = true;
running_total = 0;
addr = start_addr + urb->iso_frame_desc[i].offset;
td_len = urb->iso_frame_desc[i].length;
td_remain_len = td_len;
+ /* FIXME: Ignoring zero-length packets, can those happen? */
total_packet_count = roundup(td_len,
le16_to_cpu(urb->ep->desc.wMaxPacketSize));
+ burst_count = xhci_get_burst_count(xhci, urb->dev, urb,
+ total_packet_count);
trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
@@ -3185,7 +3210,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
for (j = 0; j < trbs_per_td; j++) {
u32 remainder = 0;
- field = 0;
+ field = TRB_TBC(burst_count);
if (first_trb) {
/* Queue the isoc TRB */