MTK xhci host controller defines some extra SW scheduling
parameters for HW to minimize the scheduling effort for
synchronous and interrupt endpoints. The parameters are
put into reseved DWs of slot context and endpoint context
+ * The TD size is the number of max packet sized packets 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.
+ */
+u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
+ unsigned trb_buffer_length, struct urb *urb)
+{
+ u32 max = 31;
+ int remainder, td_packet_count, packet_transferred;
+ unsigned int td_transfer_size = urb->transfer_buffer_length;
+ unsigned int maxp;
+
+ maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
+
+ /* 0 for the last TRB */
+ if (td_running_total + trb_buffer_length == td_transfer_size)
+ return 0;
+
+ packet_transferred = td_running_total / maxp;
+ td_packet_count = DIV_ROUND_UP(td_transfer_size, maxp);
+ remainder = td_packet_count - packet_transferred;
+
+ if (remainder > max)
+ return max << 17;
+ else
+ return remainder << 17;
+}
/* Set the TRB length, TD size, and interrupter fields. */
if (xhci->hci_version < 0x100) {
- remainder = xhci_td_remainder(
+ if (xhci->quirks & XHCI_MTK_HOST) {
+ remainder = xhci_mtk_td_remainder_quirk(
+ running_total, trb_buff_len, urb);
+ } else {
+ 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,