- Use a separate 'ret' variable for the result of prepare_transfer().
- No need to assign 'urb_priv' and 'td' until the last fragment.
- Add 'len_left' to count the bytes remaining, use instead of
  'urb->transfer_buffer_length - running_total' and to check for the
  last fragment (instead of num_trbs - which is now only used for
  the call to prepare_transfer().
- No need to pass 'more_trbs_coming' to queue_trb(), it is implied
  if TRB_CHAIN is set.
- Finish the loop when we failed to set TRB_CHAIN.

Signed-off-by: David Laight <[email protected]>
---
 drivers/usb/host/xhci-ring.c | 48 ++++++++++++++++++++------------------------
 1 file changed, 22 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index d84b183..b60932b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3260,14 +3260,14 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, 
gfp_t mem_flags,
        struct xhci_ring *ep_ring;
        unsigned int num_trbs;
        struct urb_priv *urb_priv;
-       struct xhci_td *td;
        struct scatterlist *sg;
        int num_sgs;
        int trb_buff_len, this_sg_len, running_total;
+       int len_left;
        unsigned int total_packet_count;
        bool first_trb;
        u64 addr;
-       bool more_trbs_coming;
+       int ret;
 
        struct xhci_generic_trb *start_trb;
        int start_cycle;
@@ -3281,14 +3281,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, 
gfp_t mem_flags,
        total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
                        usb_endpoint_maxp(&urb->ep->desc));
 
-       trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
+       ret = prepare_transfer(xhci, xhci->devs[slot_id],
                        ep_index, urb->stream_id,
                        num_trbs, urb, 0, mem_flags);
-       if (trb_buff_len < 0)
-               return trb_buff_len;
+       if (ret < 0)
+               return ret;
 
-       urb_priv = urb->hcpriv;
-       td = urb_priv->td[0];
 
        /*
         * Don't give the first TRB to the hardware (by toggling the cycle bit)
@@ -3299,6 +3297,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
        start_cycle = ep_ring->cycle_state;
 
        running_total = 0;
+       len_left = urb->transfer_buffer_length;
        /*
         * How much data is in the first TRB?
         *
@@ -3318,7 +3317,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
 
        first_trb = true;
        /* Queue the first TRB, even if it's zero-length */
-       do {
+       for (;;) {
                u32 field = 0;
                u32 length_field = 0;
                u32 remainder = 0;
@@ -3334,11 +3333,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, 
gfp_t mem_flags,
                /* Chain all the TRBs together; clear the chain bit in the last
                 * TRB to indicate it's the last TRB in the chain.
                 */
-               if (num_trbs > 1) {
+               if (trb_buff_len != len_left) {
                        field |= TRB_CHAIN;
                } else {
                        /* FIXME - add check for ZERO_PACKET flag before this */
-                       td->last_trb = ep_ring->enqueue;
+                       urb_priv = urb->hcpriv;
+                       urb_priv->td[0]->last_trb = ep_ring->enqueue;
                        field |= TRB_IOC;
                }
 
@@ -3348,29 +3348,28 @@ 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);
+                       remainder = xhci_td_remainder(len_left);
                } else {
                        remainder = xhci_v1_0_td_remainder(running_total,
                                        trb_buff_len, total_packet_count, urb,
-                                       num_trbs - 1);
+                                       trb_buff_len != len_left);
                }
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
                        TRB_INTR_TARGET(0);
 
-               if (num_trbs > 1)
-                       more_trbs_coming = true;
-               else
-                       more_trbs_coming = false;
-               queue_trb(xhci, ep_ring, more_trbs_coming,
+               queue_trb(xhci, ep_ring, false,
                                lower_32_bits(addr),
                                upper_32_bits(addr),
                                length_field,
                                field | TRB_TYPE(TRB_NORMAL));
-               --num_trbs;
+
+               /* If we didn't set the chain bit, we must have finished */
+               if (!(field & TRB_CHAIN))
+                       break;
+
                running_total += trb_buff_len;
+               len_left -= trb_buff_len;
 
                /* Calculate length for next transfer --
                 * Are we done queueing all the TRBs for this sg entry?
@@ -3378,8 +3377,6 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
                this_sg_len -= trb_buff_len;
                if (this_sg_len == 0) {
                        --num_sgs;
-                       if (num_sgs == 0)
-                               break;
                        sg = sg_next(sg);
                        addr = (u64) sg_dma_address(sg);
                        this_sg_len = sg_dma_len(sg);
@@ -3390,10 +3387,9 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
                trb_buff_len = TRB_MAX_BUFF_SIZE -
                        (addr & (TRB_MAX_BUFF_SIZE - 1));
                trb_buff_len = min_t(int, trb_buff_len, this_sg_len);
-               if (running_total + trb_buff_len > urb->transfer_buffer_length)
-                       trb_buff_len =
-                               urb->transfer_buffer_length - running_total;
-       } while (running_total < urb->transfer_buffer_length);
+               if (trb_buff_len > len_left)
+                       trb_buff_len = len_left;
+       }
 
        giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
                        start_cycle, start_trb);
-- 
1.8.1.2



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to