|
@@ -3028,21 +3028,6 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
|
return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * The TD size is the number of bytes remaining in the TD (including this TRB),
|
|
|
- * right shifted by 10.
|
|
|
- * It must fit in bits 21:17, so it can't be bigger than 31.
|
|
|
- */
|
|
|
-static u32 xhci_td_remainder(unsigned int remainder)
|
|
|
-{
|
|
|
- u32 max = (1 << (21 - 17 + 1)) - 1;
|
|
|
-
|
|
|
- if ((remainder >> 10) >= max)
|
|
|
- return max << 17;
|
|
|
- else
|
|
|
- return (remainder >> 10) << 17;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* For xHCI 1.0 host controllers, TD size is the number of max packet sized
|
|
|
* packets remaining in the TD (*not* including this TRB).
|
|
@@ -3055,30 +3040,36 @@ static u32 xhci_td_remainder(unsigned int remainder)
|
|
|
*
|
|
|
* TD size = total_packet_count - packets_transferred
|
|
|
*
|
|
|
- * It must fit in bits 21:17, so it can't be bigger than 31.
|
|
|
+ * For xHCI 0.96 and older, TD size field should be the remaining bytes
|
|
|
+ * including this TRB, right shifted by 10
|
|
|
+ *
|
|
|
+ * For all hosts it must fit in bits 21:17, so it can't be bigger than 31.
|
|
|
+ * This is taken care of in the TRB_TD_SIZE() macro
|
|
|
+ *
|
|
|
* The last TRB in a TD must have the TD size set to zero.
|
|
|
*/
|
|
|
-static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
|
|
|
- unsigned int total_packet_count, struct urb *urb,
|
|
|
- unsigned int num_trbs_left)
|
|
|
+static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
|
|
|
+ int trb_buff_len, unsigned int td_total_len,
|
|
|
+ struct urb *urb, unsigned int num_trbs_left)
|
|
|
{
|
|
|
- int packets_transferred;
|
|
|
+ u32 maxp, total_packet_count;
|
|
|
+
|
|
|
+ if (xhci->hci_version < 0x100)
|
|
|
+ return ((td_total_len - transferred) >> 10);
|
|
|
+
|
|
|
+ maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
|
|
|
+ total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
|
|
|
|
|
|
/* One TRB with a zero-length data packet. */
|
|
|
- if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
|
|
|
+ if (num_trbs_left == 0 || (transferred == 0 && trb_buff_len == 0) ||
|
|
|
+ trb_buff_len == td_total_len)
|
|
|
return 0;
|
|
|
|
|
|
- /* All the TRB queueing functions don't count the current TRB in
|
|
|
- * running_total.
|
|
|
- */
|
|
|
- packets_transferred = (running_total + trb_buff_len) /
|
|
|
- GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
|
|
|
-
|
|
|
- if ((total_packet_count - packets_transferred) > 31)
|
|
|
- return 31 << 17;
|
|
|
- return (total_packet_count - packets_transferred) << 17;
|
|
|
+ /* Queueing functions don't count the current TRB into transferred */
|
|
|
+ return (total_packet_count - ((transferred + trb_buff_len) / maxp));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
|
struct urb *urb, int slot_id, unsigned int ep_index)
|
|
|
{
|
|
@@ -3200,17 +3191,12 @@ 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);
|
|
|
- } else {
|
|
|
- remainder = xhci_v1_0_td_remainder(running_total,
|
|
|
- trb_buff_len, total_packet_count, urb,
|
|
|
- num_trbs - 1);
|
|
|
- }
|
|
|
+ remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
|
|
|
+ urb->transfer_buffer_length,
|
|
|
+ urb, num_trbs - 1);
|
|
|
+
|
|
|
length_field = TRB_LEN(trb_buff_len) |
|
|
|
- remainder |
|
|
|
+ TRB_TD_SIZE(remainder) |
|
|
|
TRB_INTR_TARGET(0);
|
|
|
|
|
|
if (num_trbs > 1)
|
|
@@ -3373,17 +3359,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
|
field |= TRB_ISP;
|
|
|
|
|
|
/* 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);
|
|
|
- }
|
|
|
+ remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
|
|
|
+ urb->transfer_buffer_length,
|
|
|
+ urb, num_trbs - 1);
|
|
|
+
|
|
|
length_field = TRB_LEN(trb_buff_len) |
|
|
|
- remainder |
|
|
|
+ TRB_TD_SIZE(remainder) |
|
|
|
TRB_INTR_TARGET(0);
|
|
|
|
|
|
if (num_trbs > 1)
|
|
@@ -3421,7 +3402,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
|
struct usb_ctrlrequest *setup;
|
|
|
struct xhci_generic_trb *start_trb;
|
|
|
int start_cycle;
|
|
|
- u32 field, length_field;
|
|
|
+ u32 field, length_field, remainder;
|
|
|
struct urb_priv *urb_priv;
|
|
|
struct xhci_td *td;
|
|
|
|
|
@@ -3494,9 +3475,15 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
|
else
|
|
|
field = TRB_TYPE(TRB_DATA);
|
|
|
|
|
|
+ remainder = xhci_td_remainder(xhci, 0,
|
|
|
+ urb->transfer_buffer_length,
|
|
|
+ urb->transfer_buffer_length,
|
|
|
+ urb, 1);
|
|
|
+
|
|
|
length_field = TRB_LEN(urb->transfer_buffer_length) |
|
|
|
- xhci_td_remainder(urb->transfer_buffer_length) |
|
|
|
+ TRB_TD_SIZE(remainder) |
|
|
|
TRB_INTR_TARGET(0);
|
|
|
+
|
|
|
if (urb->transfer_buffer_length > 0) {
|
|
|
if (setup->bRequestType & USB_DIR_IN)
|
|
|
field |= TRB_DIR_IN;
|
|
@@ -3825,17 +3812,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
|
trb_buff_len = td_remain_len;
|
|
|
|
|
|
/* Set the TRB length, TD size, & interrupter fields. */
|
|
|
- if (xhci->hci_version < 0x100) {
|
|
|
- remainder = xhci_td_remainder(
|
|
|
- td_len - running_total);
|
|
|
- } else {
|
|
|
- remainder = xhci_v1_0_td_remainder(
|
|
|
- running_total, trb_buff_len,
|
|
|
- total_packet_count, urb,
|
|
|
- (trbs_per_td - j - 1));
|
|
|
- }
|
|
|
+ remainder = xhci_td_remainder(xhci, running_total,
|
|
|
+ trb_buff_len, td_len,
|
|
|
+ urb, trbs_per_td - j - 1);
|
|
|
+
|
|
|
length_field = TRB_LEN(trb_buff_len) |
|
|
|
- remainder |
|
|
|
+ TRB_TD_SIZE(remainder) |
|
|
|
TRB_INTR_TARGET(0);
|
|
|
|
|
|
queue_trb(xhci, ep_ring, more_trbs_coming,
|