From 4aa2442f2096062009441dfde66f6a38ed79a211 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 19 Apr 2011 17:43:33 -0700 Subject: [PATCH] --- yaml --- r: 248803 b: refs/heads/master c: b61d378f2da41c748aba6ca19d77e1e1c02bcea5 h: refs/heads/master i: 248801: edc3aa99ac7497a68aebe27d04cf1fbaae2ccda3 248799: 5805adfebb8967e5ad283c512554872876b0b43f v: v3 --- [refs] | 2 +- trunk/drivers/usb/host/xhci-ring.c | 41 +++++++++++++++++++++++++++++- trunk/drivers/usb/host/xhci.h | 1 + 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index bad253e32b01..fb001fb81890 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5cd43e33b9519143f06f507dd7cbee6b7a621885 +refs/heads/master: b61d378f2da41c748aba6ca19d77e1e1c02bcea5 diff --git a/trunk/drivers/usb/host/xhci-ring.c b/trunk/drivers/usb/host/xhci-ring.c index cc5963263a65..396f8d2a2e8d 100644 --- a/trunk/drivers/usb/host/xhci-ring.c +++ b/trunk/drivers/usb/host/xhci-ring.c @@ -3144,6 +3144,42 @@ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, return roundup(total_packet_count, max_burst + 1) - 1; } +/* + * Returns the number of packets in the last "burst" of packets. This field is + * valid for all speeds of devices. USB 2.0 devices can only do one "burst", so + * the last burst packet count is equal to the total number of packets in the + * TD. SuperSpeed endpoints can have up to 3 bursts. All but the last burst + * must contain (bMaxBurst + 1) number of packets, but the last burst can + * contain 1 to (bMaxBurst + 1) packets. + */ +static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, + struct usb_device *udev, + struct urb *urb, unsigned int total_packet_count) +{ + unsigned int max_burst; + unsigned int residue; + + if (xhci->hci_version < 0x100) + return 0; + + switch (udev->speed) { + case USB_SPEED_SUPER: + /* bMaxBurst is zero based: 0 means 1 packet per burst */ + max_burst = urb->ep->ss_ep_comp.bMaxBurst; + residue = total_packet_count % (max_burst + 1); + /* If residue is zero, the last burst contains (max_burst + 1) + * number of packets, but the TLBPC field is zero-based. + */ + if (residue == 0) + return max_burst; + return residue - 1; + default: + if (total_packet_count == 0) + return 0; + return total_packet_count - 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) @@ -3186,6 +3222,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, for (i = 0; i < num_tds; i++) { unsigned int total_packet_count; unsigned int burst_count; + unsigned int residue; first_trb = true; running_total = 0; @@ -3197,6 +3234,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, le16_to_cpu(urb->ep->desc.wMaxPacketSize)); burst_count = xhci_get_burst_count(xhci, urb->dev, urb, total_packet_count); + residue = xhci_get_last_burst_packet_count(xhci, + urb->dev, urb, total_packet_count); trbs_per_td = count_isoc_trbs_needed(xhci, urb, i); @@ -3210,7 +3249,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 = TRB_TBC(burst_count); + field = TRB_TBC(burst_count) | TRB_TLBPC(residue); if (first_trb) { /* Queue the isoc TRB */ diff --git a/trunk/drivers/usb/host/xhci.h b/trunk/drivers/usb/host/xhci.h index 87ec3b079728..db661543a805 100644 --- a/trunk/drivers/usb/host/xhci.h +++ b/trunk/drivers/usb/host/xhci.h @@ -944,6 +944,7 @@ struct xhci_event_cmd { #define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) #define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) #define TRB_TBC(p) (((p) & 0x3) << 7) +#define TRB_TLBPC(p) (((p) & 0xf) << 16) /* Cycle bit - indicates TRB ownership by HC or HCD */ #define TRB_CYCLE (1<<0)