xhci 1.0: Update TD size field format.
[pandora-kernel.git] / drivers / usb / host / xhci-ring.c
index 766f6a6..27d690d 100644 (file)
@@ -2655,6 +2655,35 @@ static u32 xhci_td_remainder(unsigned int remainder)
                return (remainder >> 10) << 17;
 }
 
+/*
+ * For xHCI 1.0 host controllers, TD size is the number of packets remaining in
+ * the TD (*not* including this TRB).
+ *
+ * Total TD packet count = total_packet_count =
+ *     roundup(TD size in bytes / wMaxPacketSize)
+ *
+ * Packets transferred up to and including this TRB = packets_transferred =
+ *     rounddown(total bytes transferred including this TRB / wMaxPacketSize)
+ *
+ * TD size = total_packet_count - packets_transferred
+ *
+ * It must fit in bits 21:17, so it can't be bigger than 31.
+ */
+
+static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
+               unsigned int total_packet_count, struct urb *urb)
+{
+       int packets_transferred;
+
+       /* All the TRB queueing functions don't count the current TRB in
+        * running_total.
+        */
+       packets_transferred = (running_total + trb_buff_len) /
+               le16_to_cpu(urb->ep->desc.wMaxPacketSize);
+
+       return xhci_td_remainder(total_packet_count - packets_transferred);
+}
+
 static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                struct urb *urb, int slot_id, unsigned int ep_index)
 {
@@ -2665,6 +2694,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        struct scatterlist *sg;
        int num_sgs;
        int trb_buff_len, this_sg_len, running_total;
+       unsigned int total_packet_count;
        bool first_trb;
        u64 addr;
        bool more_trbs_coming;
@@ -2678,6 +2708,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
        num_trbs = count_sg_trbs_needed(xhci, urb);
        num_sgs = urb->num_sgs;
+       total_packet_count = roundup(urb->transfer_buffer_length,
+                       le16_to_cpu(urb->ep->desc.wMaxPacketSize));
 
        trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
                        ep_index, urb->stream_id,
@@ -2758,11 +2790,20 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                        (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
                                        (unsigned int) addr + trb_buff_len);
                }
-               remainder = xhci_td_remainder(urb->transfer_buffer_length -
-                               running_total) ;
+
+               /* Set the TRB length, TD size, and interrupter fields. */
+               if (xhci->hci_version < 0x100) {
+                       remainder = xhci_td_remainder(
+                                       urb->transfer_buffer_length -
+                                       running_total);
+               } else {
+                       remainder = xhci_v1_0_td_remainder(running_total,
+                                       trb_buff_len, total_packet_count, urb);
+               }
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
+
                if (num_trbs > 1)
                        more_trbs_coming = true;
                else
@@ -2819,6 +2860,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        u32 field, length_field;
 
        int running_total, trb_buff_len, ret;
+       unsigned int total_packet_count;
        u64 addr;
 
        if (urb->num_sgs)
@@ -2873,6 +2915,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        start_cycle = ep_ring->cycle_state;
 
        running_total = 0;
+       total_packet_count = roundup(urb->transfer_buffer_length,
+                       le16_to_cpu(urb->ep->desc.wMaxPacketSize));
        /* How much data is in the first TRB? */
        addr = (u64) urb->transfer_dma;
        trb_buff_len = TRB_MAX_BUFF_SIZE -
@@ -2910,11 +2954,19 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                if (usb_urb_dir_in(urb))
                        field |= TRB_ISP;
 
-               remainder = xhci_td_remainder(urb->transfer_buffer_length -
-                               running_total);
+               /* Set the TRB length, TD size, and interrupter fields. */
+               if (xhci->hci_version < 0x100) {
+                       remainder = xhci_td_remainder(
+                                       urb->transfer_buffer_length -
+                                       running_total);
+               } else {
+                       remainder = xhci_v1_0_td_remainder(running_total,
+                                       trb_buff_len, total_packet_count, urb);
+               }
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
+
                if (num_trbs > 1)
                        more_trbs_coming = true;
                else
@@ -3111,12 +3163,15 @@ 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++) {
-               first_trb = true;
+               unsigned int total_packet_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;
+               total_packet_count = roundup(td_len,
+                               le16_to_cpu(urb->ep->desc.wMaxPacketSize));
 
                trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
 
@@ -3172,10 +3227,19 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        if (trb_buff_len > td_remain_len)
                                trb_buff_len = td_remain_len;
 
-                       remainder = xhci_td_remainder(td_len - running_total);
+                       /* Set the TRB length, TD size, & interrupter fields. */
+                       if (xhci->hci_version < 0x100) {
+                               remainder = xhci_td_remainder(
+                                               td_len - running_total);
+                       } else {
+                               remainder = xhci_v1_0_td_remainder(
+                                               running_total, trb_buff_len,
+                                               total_packet_count, urb);
+                       }
                        length_field = TRB_LEN(trb_buff_len) |
                                remainder |
                                TRB_INTR_TARGET(0);
+
                        queue_trb(xhci, ep_ring, false, more_trbs_coming,
                                lower_32_bits(addr),
                                upper_32_bits(addr),