Merge 4.3-rc7 into usb-next
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / xhci-ring.c
index 48d2d40a53bda8e060b577a15c18a587db46ef33..fa836251ca21e4f19c59b3fd37b3b788b7b81008 100644 (file)
@@ -2191,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                }
        /* Fast path - was this the last TRB in the TD for this URB? */
        } else if (event_trb == td->last_trb) {
+               if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+                       return finish_td(xhci, td, event_trb, event, ep,
+                                        status, false);
+
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
@@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                        td->urb->actual_length +=
                                TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+               if (trb_comp_code == COMP_SHORT_TX) {
+                       xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+                       td->urb_length_set = true;
+                       return 0;
+               }
        }
 
        return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        u32 trb_comp_code;
        int ret = 0;
        int td_num = 0;
+       bool handling_skipped_tds = false;
 
        slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
        xdev = xhci->devs[slot_id];
@@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                ep->skip = true;
                xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
                goto cleanup;
+       case COMP_PING_ERR:
+               ep->skip = true;
+               xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+               goto cleanup;
        default:
                if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
                        status = 0;
@@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                                 ep, &status);
 
 cleanup:
+
+
+               handling_skipped_tds = ep->skip &&
+                       trb_comp_code != COMP_MISSED_INT &&
+                       trb_comp_code != COMP_PING_ERR;
+
                /*
-                * Do not update event ring dequeue pointer if ep->skip is set.
-                * Will roll back to continue process missed tds.
+                * Do not update event ring dequeue pointer if we're in a loop
+                * processing missed tds.
                 */
-               if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+               if (!handling_skipped_tds)
                        inc_deq(xhci, xhci->event_ring);
-               }
 
                if (ret) {
                        urb = td->urb;
@@ -2587,7 +2607,7 @@ cleanup:
         * Process them as short transfer until reach the td pointed by
         * the event.
         */
-       } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+       } while (handling_skipped_tds);
 
        return 0;
 }
@@ -3028,21 +3048,6 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
 }
 
-/*
- * The TD size is the number of bytes remaining in the TD (including this TRB),
- * right shifted by 10.
- * It must fit in bits 21:17, so it can't be bigger than 31.
- */
-static u32 xhci_td_remainder(unsigned int remainder)
-{
-       u32 max = (1 << (21 - 17 + 1)) - 1;
-
-       if ((remainder >> 10) >= max)
-               return max << 17;
-       else
-               return (remainder >> 10) << 17;
-}
-
 /*
  * For xHCI 1.0 host controllers, TD size is the number of max packet sized
  * packets remaining in the TD (*not* including this TRB).
@@ -3055,30 +3060,36 @@ static u32 xhci_td_remainder(unsigned int remainder)
  *
  * TD size = total_packet_count - packets_transferred
  *
- * It must fit in bits 21:17, so it can't be bigger than 31.
+ * For xHCI 0.96 and older, TD size field should be the remaining bytes
+ * including this TRB, right shifted by 10
+ *
+ * For all hosts it must fit in bits 21:17, so it can't be bigger than 31.
+ * This is taken care of in the TRB_TD_SIZE() macro
+ *
  * The last TRB in a TD must have the TD size set to zero.
  */
-static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
-               unsigned int total_packet_count, struct urb *urb,
-               unsigned int num_trbs_left)
+static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
+                             int trb_buff_len, unsigned int td_total_len,
+                             struct urb *urb, unsigned int num_trbs_left)
 {
-       int packets_transferred;
+       u32 maxp, total_packet_count;
+
+       if (xhci->hci_version < 0x100)
+               return ((td_total_len - transferred) >> 10);
+
+       maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
+       total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
 
        /* One TRB with a zero-length data packet. */
-       if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
+       if (num_trbs_left == 0 || (transferred == 0 && trb_buff_len == 0) ||
+           trb_buff_len == td_total_len)
                return 0;
 
-       /* All the TRB queueing functions don't count the current TRB in
-        * running_total.
-        */
-       packets_transferred = (running_total + trb_buff_len) /
-               GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
-
-       if ((total_packet_count - packets_transferred) > 31)
-               return 31 << 17;
-       return (total_packet_count - packets_transferred) << 17;
+       /* Queueing functions don't count the current TRB into transferred */
+       return (total_packet_count - ((transferred + trb_buff_len) / maxp));
 }
 
+
 static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                struct urb *urb, int slot_id, unsigned int ep_index)
 {
@@ -3200,17 +3211,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                }
 
                /* 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,
-                                       num_trbs - 1);
-               }
+               remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
+                                          urb->transfer_buffer_length,
+                                          urb, num_trbs - 1);
+
                length_field = TRB_LEN(trb_buff_len) |
-                       remainder |
+                       TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
 
                if (num_trbs > 1)
@@ -3373,17 +3379,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        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,
-                                       num_trbs - 1);
-               }
+               remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
+                                          urb->transfer_buffer_length,
+                                          urb, num_trbs - 1);
+
                length_field = TRB_LEN(trb_buff_len) |
-                       remainder |
+                       TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
 
                if (num_trbs > 1)
@@ -3421,7 +3422,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        struct usb_ctrlrequest *setup;
        struct xhci_generic_trb *start_trb;
        int start_cycle;
-       u32 field, length_field;
+       u32 field, length_field, remainder;
        struct urb_priv *urb_priv;
        struct xhci_td *td;
 
@@ -3494,9 +3495,15 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        else
                field = TRB_TYPE(TRB_DATA);
 
+       remainder = xhci_td_remainder(xhci, 0,
+                                  urb->transfer_buffer_length,
+                                  urb->transfer_buffer_length,
+                                  urb, 1);
+
        length_field = TRB_LEN(urb->transfer_buffer_length) |
-               xhci_td_remainder(urb->transfer_buffer_length) |
+               TRB_TD_SIZE(remainder) |
                TRB_INTR_TARGET(0);
+
        if (urb->transfer_buffer_length > 0) {
                if (setup->bRequestType & USB_DIR_IN)
                        field |= TRB_DIR_IN;
@@ -3825,17 +3832,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                trb_buff_len = td_remain_len;
 
                        /* 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,
-                                               (trbs_per_td - j - 1));
-                       }
+                       remainder = xhci_td_remainder(xhci, running_total,
+                                                  trb_buff_len, td_len,
+                                                  urb, trbs_per_td - j - 1);
+
                        length_field = TRB_LEN(trb_buff_len) |
-                               remainder |
+                               TRB_TD_SIZE(remainder) |
                                TRB_INTR_TARGET(0);
 
                        queue_trb(xhci, ep_ring, more_trbs_coming,