struct scatterlist *sg = NULL;
        bool more_trbs_coming = true;
        bool need_zero_pkt = false;
-       unsigned int num_trbs, last_trb_num, i;
+       bool first_trb = true;
+       unsigned int num_trbs;
        unsigned int start_cycle, num_sgs = 0;
-       unsigned int running_total, block_len, trb_buff_len, full_len;
+       unsigned int enqd_len, block_len, trb_buff_len, full_len;
        int ret;
        u32 field, length_field, remainder;
        u64 addr;
        if (!ring)
                return -EINVAL;
 
+       full_len = urb->transfer_buffer_length;
        /* If we have scatter/gather list, we use it. */
        if (urb->num_sgs) {
                num_sgs = urb->num_mapped_sgs;
                sg = urb->sg;
+               addr = (u64) sg_dma_address(sg);
+               block_len = sg_dma_len(sg);
                num_trbs = count_sg_trbs_needed(urb);
-       } else
+       } else {
                num_trbs = count_trbs_needed(urb);
-
+               addr = (u64) urb->transfer_dma;
+               block_len = full_len;
+       }
        ret = prepare_transfer(xhci, xhci->devs[slot_id],
                        ep_index, urb->stream_id,
                        num_trbs, urb, 0, mem_flags);
 
        urb_priv = urb->hcpriv;
 
-       last_trb_num = num_trbs - 1;
-
        /* Deal with URB_ZERO_PACKET - need one more td/trb */
        if (urb->transfer_flags & URB_ZERO_PACKET && urb_priv->length > 1)
                need_zero_pkt = true;
        start_trb = &ring->enqueue->generic;
        start_cycle = ring->cycle_state;
 
-       full_len = urb->transfer_buffer_length;
-       running_total = 0;
-       block_len = 0;
-
        /* Queue the TRBs, even if they are zero-length */
-       for (i = 0; i < num_trbs; i++) {
+       for (enqd_len = 0; enqd_len < full_len; enqd_len += trb_buff_len) {
                field = TRB_TYPE(TRB_NORMAL);
 
-               if (block_len == 0) {
-                       /* A new contiguous block. */
-                       if (sg) {
-                               addr = (u64) sg_dma_address(sg);
-                               block_len = sg_dma_len(sg);
-                       } else {
-                               addr = (u64) urb->transfer_dma;
-                               block_len = full_len;
-                       }
-                       /* TRB buffer should not cross 64KB boundaries */
-                       trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr);
-                       trb_buff_len = min_t(unsigned int,
-                                                               trb_buff_len,
-                                                               block_len);
-               } else {
-                       /* Further through the contiguous block. */
-                       trb_buff_len = block_len;
-                       if (trb_buff_len > TRB_MAX_BUFF_SIZE)
-                               trb_buff_len = TRB_MAX_BUFF_SIZE;
-               }
+               /* TRB buffer should not cross 64KB boundaries */
+               trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr);
+               trb_buff_len = min_t(unsigned int, trb_buff_len, block_len);
 
-               if (running_total + trb_buff_len > full_len)
-                       trb_buff_len = full_len - running_total;
+               if (enqd_len + trb_buff_len > full_len)
+                       trb_buff_len = full_len - enqd_len;
 
                /* Don't change the cycle bit of the first TRB until later */
-               if (i == 0) {
+               if (first_trb) {
+                       first_trb = false;
                        if (start_cycle == 0)
                                field |= TRB_CYCLE;
                } else
                /* Chain all the TRBs together; clear the chain bit in the last
                 * TRB to indicate it's the last TRB in the chain.
                 */
-               if (i < last_trb_num) {
+               if (enqd_len + trb_buff_len < full_len) {
                        field |= TRB_CHAIN;
                } else {
                        field |= TRB_IOC;
                        field |= TRB_ISP;
 
                /* Set the TRB length, TD size, and interrupter fields. */
-               remainder = xhci_td_remainder(xhci, running_total,
-                                                       trb_buff_len, full_len,
-                                                       urb, more_trbs_coming);
+               remainder = xhci_td_remainder(xhci, enqd_len, trb_buff_len,
+                                             full_len, urb, more_trbs_coming);
+
                length_field = TRB_LEN(trb_buff_len) |
                        TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
                                length_field,
                                field);
 
-               running_total += trb_buff_len;
                addr += trb_buff_len;
                block_len -= trb_buff_len;
 
-               if (sg) {
-                       if (block_len == 0) {
-                               /* New sg entry */
-                               --num_sgs;
-                               if (num_sgs == 0)
-                                       break;
+               if (sg && block_len == 0) {
+                       /* New sg entry */
+                       --num_sgs;
+                       if (num_sgs != 0) {
                                sg = sg_next(sg);
+                               block_len = sg_dma_len(sg);
+                               addr = (u64) sg_dma_address(sg);
                        }
                }
        }
                queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field);
        }
 
-       check_trb_math(urb, running_total);
+       check_trb_math(urb, enqd_len);
        giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
                        start_cycle, start_trb);
        return 0;