- 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 <david.laight@xxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html