summaryrefslogtreecommitdiff
path: root/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c
diff options
context:
space:
mode:
Diffstat (limited to 'cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c')
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c80
1 files changed, 78 insertions, 2 deletions
diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c
index 2e49de820b..43c7de559d 100644
--- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c
+++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c
@@ -38,6 +38,10 @@
* buffer low/full speed data so the host collects it at high speed.
*/
+#if _USB_T3_WBTIMEOUT_PATCH
+extern void chip_flush_memory(void);
+#endif
+
/*-------------------------------------------------------------------------*/
/* fill a qtd, returning how much of the buffer we were able to queue up */
@@ -334,9 +338,39 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
token = hc32_to_cpu(ehci, qtd->hw_token);
/* always clean up qtds the hc de-activated */
+#if defined(MSTAR_PATCH_USB_HCD)
+retry_xacterr:
+#endif
if ((token & QTD_STS_ACTIVE) == 0) {
-
+ /* on STALL, error, and short reads this urb must
+ * complete and all its qtds must be recycled.
+ */
if ((token & QTD_STS_HALT) != 0) {
+#if defined(MSTAR_PATCH_USB_HCD)
+ /* retry transaction errors until we
+ * reach the software xacterr limit
+ */
+ if ((token & QTD_STS_XACT)
+ && (QTD_CERR(token) == 0)
+ && (--qh->xacterrs > 0)
+ && (!urb->unlinked)) {
+ ehci_dbg (ehci, "detected XactErr len %d/%d retry %d\n",
+ qtd->length - QTD_LENGTH(token), qtd->length,
+ QH_XACTERR_MAX - qh->xacterrs);
+
+ /* reset the token in the qtd and the
+ * qh overlay (which still contains
+ * the qtd) so that we pick up from
+ * where we left off
+ */
+ token &= ~QTD_STS_HALT;
+ token |= QTD_STS_ACTIVE | (EHCI_TUNE_CERR << 10);
+ qtd->hw_token = cpu_to_hc32(ehci, token);
+ wmb();
+ qh->hw_token = cpu_to_hc32(ehci, token);
+ goto retry_xacterr;
+ }
+#endif
stopped = 1;
/* magic dummy for some short reads; qh won't advance.
@@ -348,7 +382,30 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
stopped = 1;
goto halt;
}
+#if defined(MSTAR_PATCH_USB_HCD)
+#if _USB_SPLIT_MDATA_BLOCKING_PATCH
+ /* SplitXstate = 1 in qTD
+ * hub addr
+ * split complite mask
+ * Interrupt IN transaction
+ */
+ else if((token & QTD_STS_STS)
+ && (hc32_to_cpu(ehci, qh->hw_info2) & QH_HUBADDR)
+ && (hc32_to_cpu(ehci, qh->hw_info2) & QH_CMASK)
+ && usb_pipeint(urb->pipe) && usb_pipein(urb->pipe)
+ && ((urb->dev->speed == USB_SPEED_LOW)
+ || (urb->dev->speed == USB_SPEED_FULL))) {
+ u32 hw_token;
+
+ hw_token = hc32_to_cpu(ehci, qh->hw_token);
+ hw_token ^= QTD_TOGGLE;
+ hw_token &= ~QTD_STS_STS;
+ wmb ();
+ qh->hw_token = cpu_to_hc32(ehci, hw_token);
+ }
+#endif
+#endif
/* stop scanning when we reach qtds the hc is using */
} else if (likely (!stopped
&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
@@ -409,6 +466,10 @@ halt:
}
list_del (&qtd->qtd_list);
last = qtd;
+#if defined(MSTAR_PATCH_USB_HCD)
+ /* reinit the xacterr counter for the next qtd */
+ qh->xacterrs = QH_XACTERR_MAX;
+#endif
}
/* last urb's completion might still need calling */
@@ -545,7 +606,15 @@ qh_urb_transaction (
*/
for (;;) {
int this_qtd_len;
-
+#if defined(MSTAR_PATCH_USB_HCD)
+#if _USB_SHORT_PACKET_LOSE_INT_PATCH
+ if (is_input && usb_pipebulk (urb->pipe)
+ && (!(urb->transfer_flags & URB_NO_INTERRUPT))
+ && (!(urb->transfer_flags & URB_SHORT_NOT_OK))) {
+ token |= cpu_to_hc32(ehci, QTD_IOC);
+ }
+#endif
+#endif
this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
len -= this_qtd_len;
buf += this_qtd_len;
@@ -820,6 +889,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
head->qh_next.qh = qh;
head->hw_next = dma;
+#if defined(MSTAR_PATCH_USB_HCD)
+ qh->xacterrs = QH_XACTERR_MAX;
+#endif
qh->qh_state = QH_STATE_LINKED;
/* qtd completions reported later by interrupt */
}
@@ -960,6 +1032,10 @@ submit_async (
*/
if (likely (qh->qh_state == QH_STATE_IDLE))
qh_link_async (ehci, qh_get (qh));
+
+#if _USB_T3_WBTIMEOUT_PATCH
+ chip_flush_memory();
+#endif
done:
spin_unlock_irqrestore (&ehci->lock, flags);
if (unlikely (qh == NULL))