summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-04-08 16:37:29 (GMT)
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-02 23:42:56 (GMT)
commit5cd43e33b9519143f06f507dd7cbee6b7a621885 (patch)
tree21613030a78a24dab98cbcffd3a59c4d8f111e8d
parent4da6e6f247a2601ab9f1e63424e4d944ed4124f3 (diff)
downloadlinux-fsl-qoriq-5cd43e33b9519143f06f507dd7cbee6b7a621885.tar.xz
xhci 1.0: Set transfer burst count field.
The xHCI 1.0 specification adds a new field to the fourth dword in an isochronous TRB: the transfer burst count (TBC). This field is only non-zero for SuperSpeed devices. Each SS endpoint sets the bMaxBurst field in the SuperSpeed endpoint companion descriptor, which indicates how many max-packet-sized "bursts" it can handle in one service interval. The device driver may choose to burst less max packet sized chunks each service interval (which is defined by one TD). The xHCI driver indicates to the host controller how many bursts it needs to schedule through the transfer burst count field. This patch will only effect xHCI hosts that advertise 1.0 support (0x100) in the HCI version field of their capabilities register. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
-rw-r--r--drivers/usb/host/xhci-ring.c27
-rw-r--r--drivers/usb/host/xhci.h1
2 files changed, 27 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 */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 85e7798..87ec3b0 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -943,6 +943,7 @@ struct xhci_event_cmd {
/* Interrupter Target - which MSI-X vector to target the completion event at */
#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22)
#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff)
+#define TRB_TBC(p) (((p) & 0x3) << 7)
/* Cycle bit - indicates TRB ownership by HC or HCD */
#define TRB_CYCLE (1<<0)