Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165022
b: refs/heads/master
c: a448c9d
h: refs/heads/master
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Sep 23, 2009
1 parent 7ba9804 commit 3a96432
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 35 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: 3a44494e233c0fdd818d485cfea8998500543589
refs/heads/master: a448c9d8c58ff7d3f8cc2a8f835065460099b22d
26 changes: 4 additions & 22 deletions trunk/drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -934,8 +934,9 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
break;
switch (qh->qh_state) {
case QH_STATE_LINKED:
case QH_STATE_COMPLETING:
intr_deschedule (ehci, qh);
/* FALL THROUGH */
break;
case QH_STATE_IDLE:
qh_completions (ehci, qh);
break;
Expand All @@ -944,23 +945,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
qh, qh->qh_state);
goto done;
}

/* reschedule QH iff another request is queued */
if (!list_empty (&qh->qtd_list)
&& HC_IS_RUNNING (hcd->state)) {
rc = qh_schedule(ehci, qh);

/* An error here likely indicates handshake failure
* or no space left in the schedule. Neither fault
* should happen often ...
*
* FIXME kill the now-dysfunctional queued urbs
*/
if (rc != 0)
ehci_err(ehci,
"can't reschedule qh %p, err %d",
qh, rc);
}
break;

case PIPE_ISOCHRONOUS:
Expand Down Expand Up @@ -1079,12 +1063,10 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
* while the QH is active. Unlink it now;
* re-linking will call qh_refresh().
*/
if (eptype == USB_ENDPOINT_XFER_BULK) {
if (eptype == USB_ENDPOINT_XFER_BULK)
unlink_async(ehci, qh);
} else {
else
intr_deschedule(ehci, qh);
(void) qh_schedule(ehci, qh);
}
}
}
spin_unlock_irqrestore(&ehci->lock, flags);
Expand Down
12 changes: 3 additions & 9 deletions trunk/drivers/usb/host/ehci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ __acquires(ehci->lock)
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);

static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);

/*
Expand Down Expand Up @@ -555,14 +554,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
* That should be rare for interrupt transfers,
* except maybe high bandwidth ...
*/
if ((cpu_to_hc32(ehci, QH_SMASK)
& hw->hw_info2) != 0) {
intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
} else {
/* Tell the caller to start an unlink */
qh->needs_rescan = 1;
}

/* Tell the caller to start an unlink */
qh->needs_rescan = 1;
break;
/* otherwise, unlink already started */
}
Expand Down
36 changes: 33 additions & 3 deletions trunk/drivers/usb/host/ehci-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,8 +615,19 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)

static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
unsigned wait;
struct ehci_qh_hw *hw = qh->hw;
unsigned wait;
struct ehci_qh_hw *hw = qh->hw;
int rc;

/* If the QH isn't linked then there's nothing we can do
* unless we were called during a giveback, in which case
* qh_completions() has to deal with it.
*/
if (qh->qh_state != QH_STATE_LINKED) {
if (qh->qh_state == QH_STATE_COMPLETING)
qh->needs_rescan = 1;
return;
}

qh_unlink_periodic (ehci, qh);

Expand All @@ -636,6 +647,24 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->qh_state = QH_STATE_IDLE;
hw->hw_next = EHCI_LIST_END(ehci);
wmb ();

qh_completions(ehci, qh);

/* reschedule QH iff another request is queued */
if (!list_empty(&qh->qtd_list) &&
HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
rc = qh_schedule(ehci, qh);

/* An error here likely indicates handshake failure
* or no space left in the schedule. Neither fault
* should happen often ...
*
* FIXME kill the now-dysfunctional queued urbs
*/
if (rc != 0)
ehci_err(ehci, "can't reschedule qh %p, err %d\n",
qh, rc);
}
}

/*-------------------------------------------------------------------------*/
Expand Down Expand Up @@ -2213,7 +2242,8 @@ scan_periodic (struct ehci_hcd *ehci)
type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
q = q.qh->qh_next;
modified = qh_completions (ehci, temp.qh);
if (unlikely (list_empty (&temp.qh->qtd_list)))
if (unlikely(list_empty(&temp.qh->qtd_list) ||
temp.qh->needs_rescan))
intr_deschedule (ehci, temp.qh);
qh_put (temp.qh);
break;
Expand Down

0 comments on commit 3a96432

Please sign in to comment.