|
@@ -298,55 +298,57 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id,
|
|
|
xhci_writel(&ctrl->dba->doorbell[0], DB_VALUE_HOST);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 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.
|
|
|
+/*
|
|
|
+ * For xHCI 1.0 host controllers, TD size is the number of max packet sized
|
|
|
+ * packets remaining in the TD (*not* including this TRB).
|
|
|
*
|
|
|
- * @param remainder remaining packets to be sent
|
|
|
- * @return remainder if remainder is less than max else max
|
|
|
- */
|
|
|
-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;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Finds out the remanining packets to be sent
|
|
|
+ * Total TD packet count = total_packet_count =
|
|
|
+ * DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)
|
|
|
+ *
|
|
|
+ * Packets transferred up to and including this TRB = packets_transferred =
|
|
|
+ * rounddown(total bytes transferred including this TRB / wMaxPacketSize)
|
|
|
+ *
|
|
|
+ * TD size = total_packet_count - packets_transferred
|
|
|
+ *
|
|
|
+ * For xHCI 0.96 and older, TD size field should be the remaining bytes
|
|
|
+ * including this TRB, right shifted by 10
|
|
|
*
|
|
|
- * @param running_total total size sent so far
|
|
|
+ * 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.
|
|
|
+ *
|
|
|
+ * @param ctrl host controller data structure
|
|
|
+ * @param transferred total size sent so far
|
|
|
* @param trb_buff_len length of the TRB Buffer
|
|
|
- * @param total_packet_count total packet count
|
|
|
- * @param maxpacketsize max packet size of current pipe
|
|
|
- * @param num_trbs_left number of TRBs left to be processed
|
|
|
- * @return 0 if running_total or trb_buff_len is 0, else remainder
|
|
|
+ * @param td_total_len total packet count
|
|
|
+ * @param maxp max packet size of current pipe
|
|
|
+ * @param more_trbs_coming indicate last trb in TD
|
|
|
+ * @return remainder
|
|
|
*/
|
|
|
-static u32 xhci_v1_0_td_remainder(int running_total,
|
|
|
- int trb_buff_len,
|
|
|
- unsigned int total_packet_count,
|
|
|
- int maxpacketsize,
|
|
|
- unsigned int num_trbs_left)
|
|
|
+static u32 xhci_td_remainder(struct xhci_ctrl *ctrl, int transferred,
|
|
|
+ int trb_buff_len, unsigned int td_total_len,
|
|
|
+ int maxp, bool more_trbs_coming)
|
|
|
{
|
|
|
- int packets_transferred;
|
|
|
+ u32 total_packet_count;
|
|
|
+
|
|
|
+ /* MTK xHCI 0.96 contains some features from 1.0 */
|
|
|
+ if (ctrl->hci_version < 0x100 && !(ctrl->quirks & XHCI_MTK_HOST))
|
|
|
+ return ((td_total_len - transferred) >> 10);
|
|
|
|
|
|
/* One TRB with a zero-length data packet. */
|
|
|
- if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
|
|
|
+ if (!more_trbs_coming || (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) / maxpacketsize;
|
|
|
+ /* for MTK xHCI 0.96, TD size include this TRB, but not in 1.x */
|
|
|
+ if ((ctrl->quirks & XHCI_MTK_HOST) && (ctrl->hci_version < 0x100))
|
|
|
+ trb_buff_len = 0;
|
|
|
+
|
|
|
+ total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
|
|
|
|
|
|
- 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));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -572,7 +574,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
union xhci_trb *event;
|
|
|
|
|
|
int running_total, trb_buff_len;
|
|
|
- unsigned int total_packet_count;
|
|
|
+ bool more_trbs_coming = true;
|
|
|
int maxpacketsize;
|
|
|
u64 addr;
|
|
|
int ret;
|
|
@@ -636,8 +638,6 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
running_total = 0;
|
|
|
maxpacketsize = usb_maxpacket(udev, pipe);
|
|
|
|
|
|
- total_packet_count = DIV_ROUND_UP(length, maxpacketsize);
|
|
|
-
|
|
|
/* How much data is in the first TRB? */
|
|
|
/*
|
|
|
* How much data is (potentially) left before the 64KB boundary?
|
|
@@ -672,34 +672,30 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
* 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 (num_trbs > 1) {
|
|
|
field |= TRB_CHAIN;
|
|
|
- else
|
|
|
+ } else {
|
|
|
field |= TRB_IOC;
|
|
|
+ more_trbs_coming = false;
|
|
|
+ }
|
|
|
|
|
|
/* Only set interrupt on short packet for IN endpoints */
|
|
|
if (usb_pipein(pipe))
|
|
|
field |= TRB_ISP;
|
|
|
|
|
|
/* Set the TRB length, TD size, and interrupter fields. */
|
|
|
- if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) < 0x100)
|
|
|
- remainder = xhci_td_remainder(length - running_total);
|
|
|
- else
|
|
|
- remainder = xhci_v1_0_td_remainder(running_total,
|
|
|
- trb_buff_len,
|
|
|
- total_packet_count,
|
|
|
- maxpacketsize,
|
|
|
- num_trbs - 1);
|
|
|
+ remainder = xhci_td_remainder(ctrl, running_total, trb_buff_len,
|
|
|
+ length, maxpacketsize,
|
|
|
+ more_trbs_coming);
|
|
|
|
|
|
- length_field = ((trb_buff_len & TRB_LEN_MASK) |
|
|
|
- remainder |
|
|
|
- ((0 & TRB_INTR_TARGET_MASK) <<
|
|
|
- TRB_INTR_TARGET_SHIFT));
|
|
|
+ length_field = (TRB_LEN(trb_buff_len) |
|
|
|
+ TRB_TD_SIZE(remainder) |
|
|
|
+ TRB_INTR_TARGET(0));
|
|
|
|
|
|
trb_fields[0] = lower_32_bits(addr);
|
|
|
trb_fields[1] = upper_32_bits(addr);
|
|
|
trb_fields[2] = length_field;
|
|
|
- trb_fields[3] = field | (TRB_NORMAL << TRB_TYPE_SHIFT);
|
|
|
+ trb_fields[3] = field | TRB_TYPE(TRB_NORMAL);
|
|
|
|
|
|
queue_trb(ctrl, ring, (num_trbs > 1), trb_fields);
|
|
|
|
|
@@ -764,6 +760,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
|
|
|
struct xhci_ring *ep_ring;
|
|
|
union xhci_trb *event;
|
|
|
+ u32 remainder;
|
|
|
|
|
|
debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
|
|
|
req->request, req->request,
|
|
@@ -825,17 +822,17 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
/* Queue setup TRB - see section 6.4.1.2.1 */
|
|
|
/* FIXME better way to translate setup_packet into two u32 fields? */
|
|
|
field = 0;
|
|
|
- field |= TRB_IDT | (TRB_SETUP << TRB_TYPE_SHIFT);
|
|
|
+ field |= TRB_IDT | TRB_TYPE(TRB_SETUP);
|
|
|
if (start_cycle == 0)
|
|
|
field |= 0x1;
|
|
|
|
|
|
/* xHCI 1.0 6.4.1.2.1: Transfer Type field */
|
|
|
- if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) >= 0x100) {
|
|
|
+ if (ctrl->hci_version >= 0x100 || ctrl->quirks & XHCI_MTK_HOST) {
|
|
|
if (length > 0) {
|
|
|
if (req->requesttype & USB_DIR_IN)
|
|
|
- field |= (TRB_DATA_IN << TRB_TX_TYPE_SHIFT);
|
|
|
+ field |= TRB_TX_TYPE(TRB_DATA_IN);
|
|
|
else
|
|
|
- field |= (TRB_DATA_OUT << TRB_TX_TYPE_SHIFT);
|
|
|
+ field |= TRB_TX_TYPE(TRB_DATA_OUT);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -851,8 +848,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
trb_fields[1] = le16_to_cpu(req->index) |
|
|
|
le16_to_cpu(req->length) << 16;
|
|
|
/* TRB_LEN | (TRB_INTR_TARGET) */
|
|
|
- trb_fields[2] = (8 | ((0 & TRB_INTR_TARGET_MASK) <<
|
|
|
- TRB_INTR_TARGET_SHIFT));
|
|
|
+ trb_fields[2] = (TRB_LEN(8) | TRB_INTR_TARGET(0));
|
|
|
/* Immediate data in pointer */
|
|
|
trb_fields[3] = field;
|
|
|
queue_trb(ctrl, ep_ring, true, trb_fields);
|
|
@@ -862,16 +858,18 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
/* If there's data, queue data TRBs */
|
|
|
/* Only set interrupt on short packet for IN endpoints */
|
|
|
if (usb_pipein(pipe))
|
|
|
- field = TRB_ISP | (TRB_DATA << TRB_TYPE_SHIFT);
|
|
|
+ field = TRB_ISP | TRB_TYPE(TRB_DATA);
|
|
|
else
|
|
|
- field = (TRB_DATA << TRB_TYPE_SHIFT);
|
|
|
+ field = TRB_TYPE(TRB_DATA);
|
|
|
|
|
|
- length_field = (length & TRB_LEN_MASK) | xhci_td_remainder(length) |
|
|
|
- ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT);
|
|
|
+ remainder = xhci_td_remainder(ctrl, 0, length, length,
|
|
|
+ usb_maxpacket(udev, pipe), true);
|
|
|
+ length_field = TRB_LEN(length) | TRB_TD_SIZE(remainder) |
|
|
|
+ TRB_INTR_TARGET(0);
|
|
|
debug("length_field = %d, length = %d,"
|
|
|
"xhci_td_remainder(length) = %d , TRB_INTR_TARGET(0) = %d\n",
|
|
|
- length_field, (length & TRB_LEN_MASK),
|
|
|
- xhci_td_remainder(length), 0);
|
|
|
+ length_field, TRB_LEN(length),
|
|
|
+ TRB_TD_SIZE(remainder), 0);
|
|
|
|
|
|
if (length > 0) {
|
|
|
if (req->requesttype & USB_DIR_IN)
|
|
@@ -901,11 +899,10 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|
|
|
|
|
trb_fields[0] = 0;
|
|
|
trb_fields[1] = 0;
|
|
|
- trb_fields[2] = ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT);
|
|
|
+ trb_fields[2] = TRB_INTR_TARGET(0);
|
|
|
/* Event on completion */
|
|
|
trb_fields[3] = field | TRB_IOC |
|
|
|
- (TRB_STATUS << TRB_TYPE_SHIFT) |
|
|
|
- ep_ring->cycle_state;
|
|
|
+ TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state;
|
|
|
|
|
|
queue_trb(ctrl, ep_ring, false, trb_fields);
|
|
|
|