If URB_ZERO_PACKET is set on a transfer that is an integral number of maximum length packets (1k for USB3 bulk) then an additional zero length fragment must be sent.
Merge together the functions that setup single buffer and scatter-gather transfers (they aren't that different) simplifying the logic as well. In particular we note that the number of TRB passed to prepare_ring() need only be an upper limit on the number required. However we do try to only request 1 TRB when we know one is sufficient. Signed-off-by: David Laight <david.lai...@aculab.com> --- This patch is basically a rewrite of xhci_queue_bilk_tx(), the diff is synchronised rather badly so I've copied the new version below. If you try to test it, you'll need the patch that stops TDs containing LINK TRBs - otherwise it all goes horribly wrong. int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) { struct xhci_ring *ep_ring; unsigned int num_trbs; struct urb_priv *urb_priv; u32 trb_buff_len, this_sg_len; struct scatterlist *sg; u32 trb_type_flags; u32 max_packet, td_residue, len_left; u32 td_size; u64 addr; int ret; ep_ring = xhci_urb_to_transfer_ring(xhci, urb); if (unlikely(!ep_ring)) return -EINVAL; if (urb->num_sgs == 0) { sg = NULL; addr = (u64)urb->transfer_dma; this_sg_len = urb->transfer_buffer_length; num_trbs = 0; } else { sg = urb->sg; addr = (u64)sg_dma_address(sg); this_sg_len = sg_dma_len(sg); /* * We only need an upper bound for the number of TRBs. * Add in two extra TRB for each subsequent segment. */ num_trbs = (urb->num_mapped_sgs - 1) * 2; } /* One TRB for each 64k 'page' that contains data */ num_trbs += DIV_ROUND_UP((addr & (TRB_MAX_BUFF_SIZE - 1)) + urb->transfer_buffer_length, TRB_MAX_BUFF_SIZE); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); /* * For v 1.0 we need to calculate the number of TD needed to * complete the transfer. * The code here is equivalent to 4.11.2.4. */ td_residue = urb->transfer_buffer_length; if (unlikely(urb->transfer_flags & URB_ZERO_PACKET)) { /* We need an extra zero length TD */ num_trbs++; td_residue++; } td_residue = ALIGN(td_residue, max_packet) + max_packet - 1; ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, mem_flags); if (unlikely(ret < 0)) return ret; trb_type_flags = TRB_CYCLE | TRB_CHAIN | TRB_TYPE(TRB_NORMAL); /* Set interrupt on short packet for IN endpoints */ if (usb_urb_dir_in(urb)) trb_type_flags |= TRB_ISP; /* Queue the first TRB, even if it's zero-length */ len_left = urb->transfer_buffer_length; for (;;) { /* * How much data is in the TRB? * * 1. TRBs buffers can't cross 64KB boundaries. * 2. We don't want to walk off the end of this sg-list buffer. * 2. Don't exceed the driver-supplied transfer length. * (May be smaller than the sg list.) */ trb_buff_len = (~addr & (TRB_MAX_BUFF_SIZE - 1)) + 1; trb_buff_len = min_t(u32, trb_buff_len, this_sg_len); trb_buff_len = min_t(u32, trb_buff_len, len_left); td_residue -= trb_buff_len; /* TRB_CYCLE is inverted in the first TRB */ trb_type_flags ^= ep_ring->cycle_state; /* * Chain all the TRBs together; clear the chain bit in the last * TRB to indicate it's the last TRB in the chain. * The td_residue can only be 2 * max_packet - 1 if * URB_ZERO_PACKET was set, this forces a zero length packet. * For version 1.0 we could send the last fragment with * td_size set to 1 - but that is just extra logic. */ if (trb_buff_len == len_left && (trb_buff_len == 0 || td_residue < 2 * max_packet - 1)) { /* The last buffer fragment */ urb_priv = urb->hcpriv; urb_priv->td[0].last_trb = ep_ring->enqueue; /* Set TRB_IOC and clear TRB_CHAIN */ trb_type_flags ^= TRB_IOC | TRB_CHAIN; td_size = 0; } else { if (xhci->hci_version < 0x100) td_size = xhci_td_remainder(len_left); else td_size = TRB_TD_SIZE(td_residue / max_packet); } /* No need to specify 'more_trbs_coming', implied by CHAIN */ queue_trb(xhci, ep_ring, false, lower_32_bits(addr), upper_32_bits(addr), TRB_LEN(trb_buff_len) | td_size | TRB_INTR_TARGET(0), trb_type_flags); if (!(trb_type_flags & TRB_CHAIN)) break; /* We want the current TRB_CYCLE in subsequent TRB */ trb_type_flags &= ~TRB_CYCLE; /* Advance everything past this segment */ len_left -= trb_buff_len; this_sg_len -= trb_buff_len; if (this_sg_len == 0 && len_left != 0) { sg = sg_next(sg); addr = (u64)sg_dma_address(sg); this_sg_len = sg_dma_len(sg); } else { /* Buffer was split on 64k boundary. * Or we need to send a zero length packet. */ addr += trb_buff_len; } } urb_priv = urb->hcpriv; giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, &urb_priv->td[0].first_trb->generic); return 0; } drivers/usb/host/xhci-ring.c | 390 +++++++++++-------------------------------- drivers/usb/host/xhci.h | 1 + 2 files changed, 101 insertions(+), 290 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ace586c..7211223 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3082,55 +3082,6 @@ static int prepare_transfer(struct xhci_hcd *xhci, return 0; } -static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) -{ - int num_sgs, num_trbs, running_total, temp, i; - struct scatterlist *sg; - - sg = NULL; - num_sgs = urb->num_mapped_sgs; - temp = urb->transfer_buffer_length; - - num_trbs = 0; - for_each_sg(urb->sg, sg, num_sgs, i) { - unsigned int len = sg_dma_len(sg); - - /* Scatter gather list entries may cross 64KB boundaries */ - running_total = TRB_MAX_BUFF_SIZE - - (sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1)); - running_total &= TRB_MAX_BUFF_SIZE - 1; - if (running_total != 0) - num_trbs++; - - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < sg_dma_len(sg) && running_total < temp) { - num_trbs++; - running_total += TRB_MAX_BUFF_SIZE; - } - len = min_t(int, len, temp); - temp -= len; - if (temp == 0) - break; - } - return num_trbs; -} - -static void check_trb_math(struct urb *urb, int num_trbs, int running_total) -{ - if (num_trbs != 0) - dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated number of " - "TRBs, %d left\n", __func__, - urb->ep->desc.bEndpointAddress, num_trbs); - if (running_total != urb->transfer_buffer_length) - dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " - "queued %#x (%d), asked for %#x (%d)\n", - __func__, - urb->ep->desc.bEndpointAddress, - running_total, running_total, - urb->transfer_buffer_length, - urb->transfer_buffer_length); -} - static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index, unsigned int stream_id, struct xhci_generic_trb *start_trb) @@ -3232,285 +3183,144 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, return (total_packet_count - packets_transferred) << 17; } -static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, +int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) { struct xhci_ring *ep_ring; unsigned int num_trbs; struct urb_priv *urb_priv; - struct xhci_td *td; + u32 trb_buff_len, this_sg_len; struct scatterlist *sg; - int num_sgs; - int trb_buff_len, this_sg_len, running_total; - unsigned int total_packet_count; - u32 trb_cycle_invert; + u32 trb_type_flags; + u32 max_packet, td_residue, len_left; + u32 td_size; u64 addr; - bool more_trbs_coming; - - struct xhci_generic_trb *start_trb; + int ret; ep_ring = xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) + if (unlikely(!ep_ring)) return -EINVAL; - num_trbs = count_sg_trbs_needed(xhci, urb); - num_sgs = urb->num_mapped_sgs; - 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], - ep_index, urb->stream_id, - num_trbs, urb, 0, mem_flags); - if (trb_buff_len < 0) - return trb_buff_len; - - urb_priv = urb->hcpriv; - td = &urb_priv->td[0]; - - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ep_ring->enqueue->generic; - - running_total = 0; - /* - * How much data is in the first TRB? - * - * There are three forces at work for TRB buffer pointers and lengths: - * 1. We don't want to walk off the end of this sg-list entry buffer. - * 2. The transfer length that the driver requested may be smaller than - * the amount of memory allocated for this scatter-gather list. - * 3. TRBs buffers can't cross 64KB boundaries. - */ - sg = urb->sg; - addr = (u64) sg_dma_address(sg); - this_sg_len = sg_dma_len(sg); - 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 (trb_buff_len > urb->transfer_buffer_length) - trb_buff_len = urb->transfer_buffer_length; - - trb_cycle_invert = TRB_CYCLE; - /* Queue the first TRB, even if it's zero-length */ - do { - u32 field = 0; - u32 length_field = 0; - u32 remainder = 0; - - field |= ep_ring->cycle_state; - /* Don't change the cycle bit of the first TRB until later */ - field ^= trb_cycle_invert; - trb_cycle_invert = 0; - - /* 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) { - field |= TRB_CHAIN; - } else { - /* FIXME - add check for ZERO_PACKET flag before this */ - td->last_trb = ep_ring->enqueue; - field |= TRB_IOC; - } - - /* Only set interrupt on short packet for IN endpoints */ - if (usb_urb_dir_in(urb)) - field |= TRB_ISP; - - if (TRB_MAX_BUFF_SIZE - - (addr & (TRB_MAX_BUFF_SIZE - 1)) < trb_buff_len) { - xhci_warn(xhci, "WARN: sg dma xfer crosses 64KB boundaries!\n"); - xhci_dbg(xhci, "Next boundary at %#x, end dma = %#x\n", - (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1), - (unsigned int) addr + trb_buff_len); - } - - /* 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); - } - 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, - lower_32_bits(addr), - upper_32_bits(addr), - length_field, - field | TRB_TYPE(TRB_NORMAL)); - --num_trbs; - running_total += trb_buff_len; - - /* Calculate length for next transfer -- - * Are we done queueing all the TRBs for this sg entry? + if (urb->num_sgs == 0) { + sg = NULL; + addr = (u64)urb->transfer_dma; + this_sg_len = urb->transfer_buffer_length; + num_trbs = 0; + } else { + sg = urb->sg; + addr = (u64)sg_dma_address(sg); + this_sg_len = sg_dma_len(sg); + /* + * We only need an upper bound for the number of TRBs. + * Add in two extra TRB for each subsequent segment. */ - 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); - } else { - addr += trb_buff_len; - } - - 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); - - check_trb_math(urb, num_trbs, running_total); - giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, start_trb); - return 0; -} - -/* This is very similar to what ehci-q.c qtd_fill() does */ -int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) -{ - struct xhci_ring *ep_ring; - struct urb_priv *urb_priv; - struct xhci_td *td; - int num_trbs; - struct xhci_generic_trb *start_trb; - u32 trb_cycle_invert; - bool more_trbs_coming; - u32 field, length_field; - - int running_total, trb_buff_len, ret; - unsigned int total_packet_count; - u64 addr; - - if (urb->num_sgs) - return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index); + num_trbs = (urb->num_mapped_sgs - 1) * 2; + } - ep_ring = xhci_urb_to_transfer_ring(xhci, urb); - if (!ep_ring) - return -EINVAL; + /* One TRB for each 64k 'page' that contains data */ + num_trbs += DIV_ROUND_UP((addr & (TRB_MAX_BUFF_SIZE - 1)) + + urb->transfer_buffer_length, TRB_MAX_BUFF_SIZE); - num_trbs = 0; - /* How much data is (potentially) left before the 64KB boundary? */ - running_total = TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); - running_total &= TRB_MAX_BUFF_SIZE - 1; + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); - /* If there's some data on this 64KB chunk, or we have to send a - * zero-length transfer, we need at least one TRB + /* + * For v 1.0 we need to calculate the number of TD needed to + * complete the transfer. + * The code here is equivalent to 4.11.2.4. */ - if (running_total != 0 || urb->transfer_buffer_length == 0) - num_trbs++; - /* How many more 64KB chunks to transfer, how many more TRBs? */ - while (running_total < urb->transfer_buffer_length) { + td_residue = urb->transfer_buffer_length; + if (unlikely(urb->transfer_flags & URB_ZERO_PACKET)) { + /* We need an extra zero length TD */ num_trbs++; - running_total += TRB_MAX_BUFF_SIZE; + td_residue++; } - /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */ + td_residue = ALIGN(td_residue, max_packet) + max_packet - 1; ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, mem_flags); - if (ret < 0) + if (unlikely(ret < 0)) return ret; - urb_priv = urb->hcpriv; - td = &urb_priv->td[0]; + trb_type_flags = TRB_CYCLE | TRB_CHAIN | TRB_TYPE(TRB_NORMAL); - /* - * Don't give the first TRB to the hardware (by toggling the cycle bit) - * until we've finished creating all the other TRBs. The ring's cycle - * state may change as we enqueue the other TRBs, so save it too. - */ - start_trb = &ep_ring->enqueue->generic; - - running_total = 0; - total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, - usb_endpoint_maxp(&urb->ep->desc)); - /* How much data is in the first TRB? */ - addr = (u64) urb->transfer_dma; - trb_buff_len = TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1)); - if (trb_buff_len > urb->transfer_buffer_length) - trb_buff_len = urb->transfer_buffer_length; - - trb_cycle_invert = TRB_CYCLE; + /* Set interrupt on short packet for IN endpoints */ + if (usb_urb_dir_in(urb)) + trb_type_flags |= TRB_ISP; /* Queue the first TRB, even if it's zero-length */ - do { - u32 remainder = 0; - field = 0; + len_left = urb->transfer_buffer_length; + for (;;) { + /* + * How much data is in the TRB? + * + * 1. TRBs buffers can't cross 64KB boundaries. + * 2. We don't want to walk off the end of this sg-list buffer. + * 2. Don't exceed the driver-supplied transfer length. + * (May be smaller than the sg list.) + */ + trb_buff_len = (~addr & (TRB_MAX_BUFF_SIZE - 1)) + 1; + trb_buff_len = min_t(u32, trb_buff_len, this_sg_len); + trb_buff_len = min_t(u32, trb_buff_len, len_left); + td_residue -= trb_buff_len; - field |= ep_ring->cycle_state; - /* Don't change the cycle bit of the first TRB until later */ - field ^= trb_cycle_invert; - trb_cycle_invert = 0; + /* TRB_CYCLE is inverted in the first TRB */ + trb_type_flags ^= ep_ring->cycle_state; - /* Chain all the TRBs together; clear the chain bit in the last + /* + * Chain all the TRBs together; clear the chain bit in the last * TRB to indicate it's the last TRB in the chain. + * The td_residue can only be 2 * max_packet - 1 if + * URB_ZERO_PACKET was set, this forces a zero length packet. + * For version 1.0 we could send the last fragment with + * td_size set to 1 - but that is just extra logic. */ - if (num_trbs > 1) { - field |= TRB_CHAIN; + if (trb_buff_len == len_left && (trb_buff_len == 0 || + td_residue < 2 * max_packet - 1)) { + /* The last buffer fragment */ + urb_priv = urb->hcpriv; + urb_priv->td[0].last_trb = ep_ring->enqueue; + /* Set TRB_IOC and clear TRB_CHAIN */ + trb_type_flags ^= TRB_IOC | TRB_CHAIN; + td_size = 0; } else { - /* FIXME - add check for ZERO_PACKET flag before this */ - td->last_trb = ep_ring->enqueue; - field |= TRB_IOC; + if (xhci->hci_version < 0x100) + td_size = xhci_td_remainder(len_left); + else + td_size = TRB_TD_SIZE(td_residue / max_packet); } - /* Only set interrupt on short packet for IN endpoints */ - if (usb_urb_dir_in(urb)) - field |= TRB_ISP; + /* No need to specify 'more_trbs_coming', implied by CHAIN */ + queue_trb(xhci, ep_ring, false, + lower_32_bits(addr), + upper_32_bits(addr), + TRB_LEN(trb_buff_len) | td_size | + TRB_INTR_TARGET(0), + trb_type_flags); + + if (!(trb_type_flags & TRB_CHAIN)) + break; + + /* We want the current TRB_CYCLE in subsequent TRB */ + trb_type_flags &= ~TRB_CYCLE; - /* Set the TRB length, TD size, and interrupter fields. */ - if (xhci->hci_version < 0x100) { - remainder = xhci_td_remainder( - urb->transfer_buffer_length - - running_total); + /* Advance everything past this segment */ + len_left -= trb_buff_len; + this_sg_len -= trb_buff_len; + if (this_sg_len == 0 && len_left != 0) { + sg = sg_next(sg); + addr = (u64)sg_dma_address(sg); + this_sg_len = sg_dma_len(sg); } else { - remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb, - num_trbs - 1); + /* Buffer was split on 64k boundary. + * Or we need to send a zero length packet. */ + addr += trb_buff_len; } - 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, - lower_32_bits(addr), - upper_32_bits(addr), - length_field, - field | TRB_TYPE(TRB_NORMAL)); - --num_trbs; - running_total += trb_buff_len; - - /* Calculate length for next transfer */ - addr += trb_buff_len; - trb_buff_len = urb->transfer_buffer_length - running_total; - if (trb_buff_len > TRB_MAX_BUFF_SIZE) - trb_buff_len = TRB_MAX_BUFF_SIZE; - } while (running_total < urb->transfer_buffer_length); - - check_trb_math(urb, num_trbs, running_total); - giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, start_trb); + urb_priv = urb->hcpriv; + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, + &urb_priv->td[0].first_trb->generic); return 0; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 118f90b..bbdbfed 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1123,6 +1123,7 @@ struct xhci_event_cmd { /* Normal TRB fields */ /* transfer_len bitmasks - bits 0:16 */ #define TRB_LEN(p) ((p) & 0x1ffff) +#define TRB_TD_SIZE(p) (min_t(u32, (p), 31) << 17) /* Interrupter Target - which MSI-X vector to target the completion event at */ #define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) #define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html