xhci 1.0: Update TD size field format.
[pandora-kernel.git] / drivers / usb / host / xhci-ring.c
index 73f8db0..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,
@@ -2741,6 +2773,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        td->last_trb = ep_ring->enqueue;
                        field |= TRB_IOC;
                }
+
+               /* Only set interrupt on short packet for IN endpoints */
+               if (usb_urb_dir_in(urb))
+                       field |= TRB_ISP;
+
                xhci_dbg(xhci, " sg entry: dma = %#x, len = %#x (%d), "
                                "64KB boundary at %#x, end dma = %#x\n",
                                (unsigned int) addr, trb_buff_len, trb_buff_len,
@@ -2753,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
@@ -2766,12 +2812,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
-                               /* We always want to know if the TRB was short,
-                                * or we won't get an event when it completes.
-                                * (Unless we use event data TRBs, which are a
-                                * waste of space and HC resources.)
-                                */
-                               field | TRB_ISP | TRB_TYPE(TRB_NORMAL));
+                               field | TRB_TYPE(TRB_NORMAL));
                --num_trbs;
                running_total += trb_buff_len;
 
@@ -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 -
@@ -2905,11 +2949,24 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        td->last_trb = ep_ring->enqueue;
                        field |= TRB_IOC;
                }
-               remainder = xhci_td_remainder(urb->transfer_buffer_length -
-                               running_total);
+
+               /* Only set interrupt on short packet for IN endpoints */
+               if (usb_urb_dir_in(urb))
+                       field |= TRB_ISP;
+
+               /* 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
@@ -2918,12 +2975,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
-                               /* We always want to know if the TRB was short,
-                                * or we won't get an event when it completes.
-                                * (Unless we use event data TRBs, which are a
-                                * waste of space and HC resources.)
-                                */
-                               field | TRB_ISP | TRB_TYPE(TRB_NORMAL));
+                               field | TRB_TYPE(TRB_NORMAL));
                --num_trbs;
                running_total += trb_buff_len;
 
@@ -3009,7 +3061,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                  field);
 
        /* If there's data, queue data TRBs */
-       field = 0;
+       /* Only set interrupt on short packet for IN endpoints */
+       if (usb_urb_dir_in(urb))
+               field = TRB_ISP | TRB_TYPE(TRB_DATA);
+       else
+               field = TRB_TYPE(TRB_DATA);
+
        length_field = TRB_LEN(urb->transfer_buffer_length) |
                xhci_td_remainder(urb->transfer_buffer_length) |
                TRB_INTR_TARGET(0);
@@ -3020,8 +3077,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                lower_32_bits(urb->transfer_dma),
                                upper_32_bits(urb->transfer_dma),
                                length_field,
-                               /* Event on short tx */
-                               field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state);
+                               field | ep_ring->cycle_state);
        }
 
        /* Save the DMA address of the last TRB in the TD */
@@ -3107,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);
 
@@ -3145,6 +3204,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                field |= ep_ring->cycle_state;
                        }
 
+                       /* Only set interrupt on short packet for IN EPs */
+                       if (usb_urb_dir_in(urb))
+                               field |= TRB_ISP;
+
                        /* Chain all the TRBs together; clear the chain bit in
                         * the last TRB to indicate it's the last TRB in the
                         * chain.
@@ -3164,20 +3227,24 @@ 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),
                                length_field,
-                               /* We always want to know if the TRB was short,
-                                * or we won't get an event when it completes.
-                                * (Unless we use event data TRBs, which are a
-                                * waste of space and HC resources.)
-                                */
-                               field | TRB_ISP);
+                               field);
                        running_total += trb_buff_len;
 
                        addr += trb_buff_len;