v1.0 hosts need the td_size set to the number of messages (including
the final short one) that need to be sent to complete the transfer
after all the full-sized ones for the current TRB have been sent.

The code in xhci_v1_0_td_remainder() carefully copies the algorithm
from the documentation, but the value can be calculated much more
easily.

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

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bf9a20f..afd8eeb 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3272,9 +3272,9 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
        unsigned int num_trbs;
        struct urb_priv *urb_priv;
        struct scatterlist *sg;
-       u32 trb_buff_len, this_sg_len, running_total;
+       u32 trb_buff_len, this_sg_len;
        u32 len_left;
-       unsigned int total_packet_count;
+       u32 td_residue, max_packet;
        u32 trb_type_flags;
        u64 addr;
        int ret;
@@ -3287,8 +3287,19 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
                return -EINVAL;
 
        num_trbs = count_sg_trbs_needed(ep_ring, urb);
-       total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
-                       usb_endpoint_maxp(&urb->ep->desc));
+
+       /*
+        * For v1.0 endpoints we need to calculate the number of packets
+        * required to complete the request.
+        * The code here is equivalent to the calculations in section 4.11.2.4
+        *
+        * td_residue is set so that td_residue/max_packet is the number of
+        * packets required to send the data after the current partial
+        * transfer(s) have completed.
+        */
+       max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
+       td_residue = urb->transfer_buffer_length;
+       td_residue = ALIGN(td_residue, max_packet) + max_packet - 1;
 
        ret = prepare_transfer(xhci, xhci->devs[slot_id],
                        ep_index, urb->stream_id,
@@ -3313,7 +3324,6 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
        if (usb_urb_dir_in(urb))
                trb_type_flags |= TRB_ISP;
 
-       running_total = 0;
        len_left = urb->transfer_buffer_length;
 
        sg = urb->sg;
@@ -3323,7 +3333,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
        /* Queue the first TRB, even if it's zero-length */
        for (;;) {
                u32 length_field = 0;
-               u32 remainder = 0;
+               u32 td_size = 0;
                /*
                 * How much data is in the TRB?
                 *
@@ -3342,9 +3352,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
                        urb_priv->td[0]->last_trb = ep_ring->enqueue;
                        /* Request interrupt and clear chain */
                        trb_type_flags ^= TRB_IOC | TRB_CHAIN;
+                       td_residue = 0;
                } else {
                        if (trb_buff_len == 0)
                                goto next_frag;
+                       td_residue -= trb_buff_len;
                }
 
                /* Set the correct cycle bit (inverted for first TRB). */
@@ -3352,14 +3364,13 @@ 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(len_left);
+                       td_size = xhci_td_remainder(len_left);
                } else {
-                       remainder = xhci_v1_0_td_remainder(running_total,
-                                       trb_buff_len, total_packet_count, urb,
-                                       trb_buff_len != len_left);
+                       td_size = min_t(u32, td_residue / max_packet, 31) << 17;
                }
+
                length_field = TRB_LEN(trb_buff_len) |
-                       remainder |
+                       td_size |
                        TRB_INTR_TARGET(0);
 
                queue_trb(xhci, ep_ring, false,
@@ -3375,7 +3386,6 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
                /* We want the current cycle in subsequent TRB */
                trb_type_flags &= ~TRB_CYCLE;
 
-               running_total += trb_buff_len;
                len_left -= trb_buff_len;
 
                /* Advance source data pointer */
-- 
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