Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 155381
b: refs/heads/master
c: 914b701
h: refs/heads/master
i:
  155379: ef8de34
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jul 12, 2009
1 parent 553c750 commit 2dce3ef
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cb88a1b887bb8908f6e00ce29e893ea52b074940
refs/heads/master: 914b701280a76f96890ad63eb0fa99bf204b961c
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-au1xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-fsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = {
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ehci_fsl_drv_probe(struct platform_device *pdev)
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,8 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
schedule_timeout_uninterruptible(1);
goto rescan;
case QH_STATE_IDLE: /* fully unlinked */
if (qh->clearing_tt)
goto idle_timeout;
if (list_empty (&qh->qtd_list)) {
qh_put (qh);
break;
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-ixp4xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ixp4xx_ehci_probe(struct platform_device *pdev)
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-orion.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static void __init
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

/*-------------------------------------------------------------------------*/
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-ppc-of.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};


Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci-ps3.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = {
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,

.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
Expand Down
91 changes: 68 additions & 23 deletions trunk/drivers/usb/host/ehci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)

/*-------------------------------------------------------------------------*/

static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);

static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct ehci_qh *qh = ep->hcpriv;
unsigned long flags;

spin_lock_irqsave(&ehci->lock, flags);
qh->clearing_tt = 0;
if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
&& HC_IS_RUNNING(hcd->state))
qh_link_async(ehci, qh);
spin_unlock_irqrestore(&ehci->lock, flags);
}

static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
struct urb *urb, u32 token)
{

/* If an async split transaction gets an error or is unlinked,
* the TT buffer may be left in an indeterminate state. We
* have to clear the TT buffer.
*
* Note: this routine is never called for Isochronous transfers.
*/
if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
#ifdef DEBUG
struct usb_device *tt = urb->dev->tt->hub;
dev_dbg(&tt->dev,
"clear tt buffer port %d, a%d ep%d t%08x\n",
urb->dev->ttport, urb->dev->devnum,
usb_pipeendpoint(urb->pipe), token);
#endif /* DEBUG */
if (!ehci_is_TDI(ehci)
|| urb->dev->tt->hub !=
ehci_to_hcd(ehci)->self.root_hub) {
if (usb_hub_clear_tt_buffer(urb) == 0)
qh->clearing_tt = 1;
} else {

/* REVISIT ARC-derived cores don't clear the root
* hub TT buffer in this way...
*/
}
}
}

static int qtd_copy_status (
struct ehci_hcd *ehci,
struct urb *urb,
Expand Down Expand Up @@ -195,28 +244,6 @@ static int qtd_copy_status (
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out",
token, status);

/* if async CSPLIT failed, try cleaning out the TT buffer */
if (status != -EPIPE
&& urb->dev->tt
&& !usb_pipeint(urb->pipe)
&& ((token & QTD_STS_MMF) != 0
|| QTD_CERR(token) == 0)
&& (!ehci_is_TDI(ehci)
|| urb->dev->tt->hub !=
ehci_to_hcd(ehci)->self.root_hub)) {
#ifdef DEBUG
struct usb_device *tt = urb->dev->tt->hub;
dev_dbg (&tt->dev,
"clear tt buffer port %d, a%d ep%d t%08x\n",
urb->dev->ttport, urb->dev->devnum,
usb_pipeendpoint (urb->pipe), token);
#endif /* DEBUG */
/* REVISIT ARC-derived cores don't clear the root
* hub TT buffer in this way...
*/
usb_hub_clear_tt_buffer(urb);
}
}

return status;
Expand Down Expand Up @@ -407,9 +434,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* qh unlinked; token in overlay may be most current */
if (state == QH_STATE_IDLE
&& cpu_to_hc32(ehci, qtd->qtd_dma)
== qh->hw_current)
== qh->hw_current) {
token = hc32_to_cpu(ehci, qh->hw_token);

/* An unlink may leave an incomplete
* async transaction in the TT buffer.
* We have to clear it.
*/
ehci_clear_tt_buffer(ehci, qh, urb, token);
}

/* force halt for unlinked or blocked qh, so we'll
* patch the qh later and so that completions can't
* activate it while we "know" it's stopped.
Expand All @@ -435,6 +469,13 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
&& (qtd->hw_alt_next
& EHCI_LIST_END(ehci)))
last_status = -EINPROGRESS;

/* As part of low/full-speed endpoint-halt processing
* we must clear the TT buffer (11.17.5).
*/
if (unlikely(last_status != -EINPROGRESS &&
last_status != -EREMOTEIO))
ehci_clear_tt_buffer(ehci, qh, urb, token);
}

/* if we're removing something not at the queue head,
Expand Down Expand Up @@ -864,6 +905,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
__hc32 dma = QH_NEXT(ehci, qh->qh_dma);
struct ehci_qh *head;

/* Don't link a QH if there's a Clear-TT-Buffer pending */
if (unlikely(qh->clearing_tt))
return;

/* (re)start the async schedule? */
head = ehci->async;
timer_action_done (ehci, TIMER_ASYNC_OFF);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,9 @@ struct ehci_qh {
unsigned short period; /* polling interval */
unsigned short start; /* where polling starts */
#define NO_FRAME ((unsigned short)~0) /* pick new start */

struct usb_device *dev; /* access to TT */
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
} __attribute__ ((aligned (32)));

/*-------------------------------------------------------------------------*/
Expand Down

0 comments on commit 2dce3ef

Please sign in to comment.