Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 131875
b: refs/heads/master
c: 9aa09d2
h: refs/heads/master
i:
  131873: 1084eb9
  131871: d543bd5
v: v3
  • Loading branch information
Karsten Wiese authored and Greg Kroah-Hartman committed Feb 27, 2009
1 parent 55ee3cb commit 67a8dd3
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 9 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: 9a6e184c804b33a2c2ea974efcd3c9798d30cb39
refs/heads/master: 9aa09d2f8f4bc440d6db1c3414d4009642875240
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 @@ -485,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd)
* periodic_size can shrink by USBCMD update if hcc_params allows.
*/
ehci->periodic_size = DEFAULT_I_TDPS;
INIT_LIST_HEAD(&ehci->cached_itd_list);
if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
return retval;

Expand All @@ -497,6 +498,7 @@ static int ehci_init(struct usb_hcd *hcd)

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

/*
* dedicate a qh for the async ring head, since we couldn't unlink
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/usb/host/ehci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh)

static void ehci_mem_cleanup (struct ehci_hcd *ehci)
{
free_cached_itd_list(ehci);
if (ehci->async)
qh_put (ehci->async);
ehci->async = NULL;
Expand Down
56 changes: 48 additions & 8 deletions trunk/drivers/usb/host/ehci-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)

is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
stream->bEndpointAddress &= 0x0f;
stream->ep->hcpriv = NULL;
if (stream->ep)
stream->ep->hcpriv = NULL;

if (stream->rescheduled) {
ehci_info (ehci, "ep%d%s-iso rescheduled "
Expand Down Expand Up @@ -1653,14 +1654,28 @@ itd_complete (
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
iso_stream_put (ehci, stream);
/* OK to recycle this ITD now that its completion callback ran. */

done:
usb_put_urb(urb);
itd->urb = NULL;
itd->stream = NULL;
list_move(&itd->itd_list, &stream->free_list);
iso_stream_put(ehci, stream);

if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
/* OK to recycle this ITD now. */
itd->stream = NULL;
list_move(&itd->itd_list, &stream->free_list);
iso_stream_put(ehci, stream);
} else {
/* HW might remember this ITD, so we can't recycle it yet.
* Move it to a safe place until a new frame starts.
*/
list_move(&itd->itd_list, &ehci->cached_itd_list);
if (stream->refcount == 2) {
/* If iso_stream_put() were called here, stream
* would be freed. Instead, just prevent reuse.
*/
stream->ep->hcpriv = NULL;
stream->ep = NULL;
}
}
return retval;
}

Expand Down Expand Up @@ -2101,6 +2116,20 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,

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

static void free_cached_itd_list(struct ehci_hcd *ehci)
{
struct ehci_itd *itd, *n;

list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
struct ehci_iso_stream *stream = itd->stream;
itd->stream = NULL;
list_move(&itd->itd_list, &stream->free_list);
iso_stream_put(ehci, stream);
}
}

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

static void
scan_periodic (struct ehci_hcd *ehci)
{
Expand All @@ -2115,10 +2144,17 @@ scan_periodic (struct ehci_hcd *ehci)
* Touches as few pages as possible: cache-friendly.
*/
now_uframe = ehci->next_uframe;
if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
clock = ehci_readl(ehci, &ehci->regs->frame_index);
else
clock_frame = (clock >> 3) % ehci->periodic_size;
} else {
clock = now_uframe + mod - 1;
clock_frame = -1;
}
if (ehci->clock_frame != clock_frame) {
free_cached_itd_list(ehci);
ehci->clock_frame = clock_frame;
}
clock %= mod;
clock_frame = clock >> 3;

Expand Down Expand Up @@ -2277,6 +2313,10 @@ scan_periodic (struct ehci_hcd *ehci)
/* rescan the rest of this frame, then ... */
clock = now;
clock_frame = clock >> 3;
if (ehci->clock_frame != clock_frame) {
free_cached_itd_list(ehci);
ehci->clock_frame = clock_frame;
}
} else {
now_uframe++;
now_uframe %= mod;
Expand Down
6 changes: 6 additions & 0 deletions trunk/drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ struct ehci_hcd { /* one per controller */
int next_uframe; /* scan periodic, start here */
unsigned periodic_sched; /* periodic activity count */

/* list of itds completed while clock_frame was still active */
struct list_head cached_itd_list;
unsigned clock_frame;

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

Expand Down Expand Up @@ -220,6 +224,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
}
}

static void free_cached_itd_list(struct ehci_hcd *ehci);

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

#include <linux/usb/ehci_def.h>
Expand Down

0 comments on commit 67a8dd3

Please sign in to comment.