Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 317035
b: refs/heads/master
c: f428907
h: refs/heads/master
i:
  317033: 24bf1b1
  317031: 5c1e8dc
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jul 16, 2012
1 parent 201bf10 commit 49ea063
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 92 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: 18aafe64d75d0e27dae206cacf4171e4e485d285
refs/heads/master: f42890782241a60d107f23d08089a4a12b507a11
3 changes: 0 additions & 3 deletions trunk/drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,6 @@ static int ehci_init(struct usb_hcd *hcd)
else // N microframes cached
ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);

ehci->next_uframe = -1;
ehci->clock_frame = -1;

/*
* dedicate a qh for the async ring head, since we couldn't unlink
* a 'real' qh without stopping the async schedule [4.8]. use it
Expand Down
114 changes: 29 additions & 85 deletions trunk/drivers/usb/host/ehci-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,8 +497,6 @@ static void disable_periodic(struct ehci_hcd *ehci)
if (--ehci->periodic_count)
return;

ehci->next_uframe = -1; /* the periodic schedule is empty */

/* Don't turn off the schedule until PSS is 1 */
ehci_poll_PSS(ehci);
}
Expand Down Expand Up @@ -1220,7 +1218,7 @@ itd_urb_transaction (
if (likely(!list_empty(&stream->free_list))) {
itd = list_first_entry(&stream->free_list,
struct ehci_itd, itd_list);
if (itd->frame == ehci->clock_frame)
if (itd->frame == ehci->now_frame)
goto alloc_itd;
list_del (&itd->itd_list);
itd_dma = itd->itd_dma;
Expand Down Expand Up @@ -1492,7 +1490,7 @@ iso_stream_schedule (

/* Make sure scan_isoc() sees these */
if (ehci->isoc_count == 0)
ehci->next_uframe = now;
ehci->next_frame = now >> 3;
return 0;

fail:
Expand Down Expand Up @@ -1666,19 +1664,16 @@ static void itd_link_urb(
* (b) only this endpoint's completions submit URBs. It seems some silicon
* corrupts things if you reuse completed descriptors very quickly...
*/
static unsigned
itd_complete (
struct ehci_hcd *ehci,
struct ehci_itd *itd
) {
static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
{
struct urb *urb = itd->urb;
struct usb_iso_packet_descriptor *desc;
u32 t;
unsigned uframe;
int urb_index = -1;
struct ehci_iso_stream *stream = itd->stream;
struct usb_device *dev;
unsigned retval = false;
bool retval = false;

/* for each uframe with a packet */
for (uframe = 0; uframe < 8; uframe++) {
Expand Down Expand Up @@ -1917,7 +1912,7 @@ sitd_urb_transaction (
if (likely(!list_empty(&stream->free_list))) {
sitd = list_first_entry(&stream->free_list,
struct ehci_sitd, sitd_list);
if (sitd->frame == ehci->clock_frame)
if (sitd->frame == ehci->now_frame)
goto alloc_sitd;
list_del (&sitd->sitd_list);
sitd_dma = sitd->sitd_dma;
Expand Down Expand Up @@ -2071,18 +2066,15 @@ static void sitd_link_urb(
* (b) only this endpoint's completions submit URBs. It seems some silicon
* corrupts things if you reuse completed descriptors very quickly...
*/
static unsigned
sitd_complete (
struct ehci_hcd *ehci,
struct ehci_sitd *sitd
) {
static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
{
struct urb *urb = sitd->urb;
struct usb_iso_packet_descriptor *desc;
u32 t;
int urb_index = -1;
struct ehci_iso_stream *stream = sitd->stream;
struct usb_device *dev;
unsigned retval = false;
bool retval = false;

urb_index = sitd->index;
desc = &urb->iso_frame_desc [urb_index];
Expand Down Expand Up @@ -2214,64 +2206,54 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,

static void scan_isoc(struct ehci_hcd *ehci)
{
unsigned now_uframe, frame, clock, clock_frame, mod;
unsigned modified;

mod = ehci->periodic_size << 3;
unsigned uf, now_frame, frame;
unsigned fmask = ehci->periodic_size - 1;
bool modified, live;

/*
* When running, scan from last scan point up to "now"
* else clean up by scanning everything that's left.
* Touches as few pages as possible: cache-friendly.
*/
now_uframe = ehci->next_uframe;
if (ehci->rh_state >= EHCI_RH_RUNNING) {
clock = ehci_read_frame_index(ehci);
clock_frame = (clock >> 3) & (ehci->periodic_size - 1);
uf = ehci_read_frame_index(ehci);
now_frame = (uf >> 3) & fmask;
live = true;
} else {
clock = now_uframe + mod - 1;
clock_frame = -1;
now_frame = (ehci->next_frame - 1) & fmask;
live = false;
}
ehci->clock_frame = clock_frame;
clock &= mod - 1;
clock_frame = clock >> 3;
ehci->now_frame = now_frame;

frame = ehci->next_frame;
for (;;) {
union ehci_shadow q, *q_p;
__hc32 type, *hw_p;
unsigned incomplete = false;

frame = now_uframe >> 3;

restart:
/* scan each element in frame's queue for completions */
q_p = &ehci->pshadow [frame];
hw_p = &ehci->periodic [frame];
q.ptr = q_p->ptr;
type = Q_NEXT_TYPE(ehci, *hw_p);
modified = 0;
modified = false;

while (q.ptr != NULL) {
unsigned uf;
int live;

live = (ehci->rh_state >= EHCI_RH_RUNNING);
switch (hc32_to_cpu(ehci, type)) {
case Q_TYPE_ITD:
/* If this ITD is still active, leave it for
* later processing ... check the next entry.
* No need to check for activity unless the
* frame is current.
*/
if (frame == clock_frame && live) {
if (frame == now_frame && live) {
rmb();
for (uf = 0; uf < 8; uf++) {
if (q.itd->hw_transaction[uf] &
ITD_ACTIVE(ehci))
break;
}
if (uf < 8) {
incomplete = true;
q_p = &q.itd->itd_next;
hw_p = &q.itd->hw_next;
type = Q_NEXT_TYPE(ehci,
Expand Down Expand Up @@ -2303,14 +2285,12 @@ static void scan_isoc(struct ehci_hcd *ehci)
* No need to check for activity unless the
* frame is current.
*/
if (((frame == clock_frame) ||
(((frame + 1) & (ehci->periodic_size - 1))
== clock_frame))
if (((frame == now_frame) ||
(((frame + 1) & fmask) == now_frame))
&& live
&& (q.sitd->hw_results &
SITD_ACTIVE(ehci))) {

incomplete = true;
q_p = &q.sitd->sitd_next;
hw_p = &q.sitd->hw_next;
type = Q_NEXT_TYPE(ehci,
Expand Down Expand Up @@ -2347,50 +2327,14 @@ static void scan_isoc(struct ehci_hcd *ehci)
}

/* assume completion callbacks modify the queue */
if (unlikely (modified)) {
if (likely(ehci->isoc_count > 0))
goto restart;
/* short-circuit this scan */
now_uframe = clock;
break;
}
if (unlikely(modified && ehci->isoc_count > 0))
goto restart;
}

/* If we can tell we caught up to the hardware, stop now.
* We can't advance our scan without collecting the ISO
* transfers that are still pending in this frame.
*/
if (incomplete && ehci->rh_state >= EHCI_RH_RUNNING) {
ehci->next_uframe = now_uframe;
/* Stop when we have reached the current frame */
if (frame == now_frame)
break;
}

// FIXME: this assumes we won't get lapped when
// latencies climb; that should be rare, but...
// detect it, and just go all the way around.
// FLR might help detect this case, so long as latencies
// don't exceed periodic_size msec (default 1.024 sec).

// FIXME: likewise assumes HC doesn't halt mid-scan

if (now_uframe == clock) {
unsigned now;

if (ehci->rh_state < EHCI_RH_RUNNING
|| ehci->isoc_count == 0)
break;
ehci->next_uframe = now_uframe;
now = ehci_read_frame_index(ehci) & (mod - 1);
if (now_uframe == now)
break;

/* rescan the rest of this frame, then ... */
clock = now;
clock_frame = clock >> 3;
ehci->clock_frame = clock_frame;
} else {
now_uframe++;
now_uframe &= mod - 1;
}
frame = (frame + 1) & fmask;
}
ehci->next_frame = now_frame;
}
6 changes: 3 additions & 3 deletions trunk/drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,19 @@ struct ehci_hcd { /* one per controller */
struct ehci_qh *intr_unlink;
struct ehci_qh *intr_unlink_last;
unsigned intr_unlink_cycle;
int next_uframe; /* scan periodic, start here */
unsigned now_frame; /* frame from HC hardware */
unsigned next_frame; /* scan periodic, start here */
unsigned intr_count; /* intr activity count */
unsigned isoc_count; /* isoc activity count */
unsigned periodic_count; /* periodic activity count */
unsigned uframe_periodic_max; /* max periodic time per uframe */


/* list of itds & sitds completed while clock_frame was still active */
/* list of itds & sitds completed while now_frame was still active */
struct list_head cached_itd_list;
struct ehci_itd *last_itd_to_free;
struct list_head cached_sitd_list;
struct ehci_sitd *last_sitd_to_free;
unsigned clock_frame;

/* per root hub port */
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
Expand Down

0 comments on commit 49ea063

Please sign in to comment.