[alsa-devel] (no subject)
Philippe Carriere
philippe-f.carriere at wanadoo.fr
Thu Jan 29 09:35:53 CET 2009
Hi Karsten,
I successfully tested your new version of the patch and sent a
"tested:by" to linux-usb at vger.kernel.org today (see attached).
Hope it will speed up the process.
Regards,
Phil.
Le mardi 27 janvier 2009 à 01:16 +0100, Karsten Wiese a écrit :
> Am Dienstag, 14. Oktober 2008 schrieb Philippe Carriere:
> > Might this patch (the original one, without features yet implemented in
> > 2.6.26, and an extremely slight modification to fit it) I use on Fedora
> > kernel (the patch also applies as it stands to vanilla) save works and
> > time ?
>
> I resent the patch to linux-usb at vger.kernel.org today.
> Maybe it helps, if you post a "tested-by:" there.
>
> Regards,
> Karsten
>
> pièce jointe message de courriel (forwarded message), "Karsten Wiese
> <fzu at wemgehoertderstaat.de>: [RESEND][PATCH] USB: Prevent EHCI ITDs
> reusage while frame is active"
> > -------- Message transféré --------
> > De: Karsten Wiese <fzu at wemgehoertderstaat.de>
> > À: David Brownell <david-b at pacbell.net>
> > Cc: linux-usb at vger.kernel.org
> > Sujet: [RESEND][PATCH] USB: Prevent EHCI ITDs reusage while frame is
> > active
> > Date: Mon, 26 Jan 2009 14:32:51 +0100
> >
> > pièce jointe document texte brut (forwarded message)
> > Hi,
> >
> > this is a refresh to let patch fit ontop 2.6.29-rc2.
> > Changes from previous version:
> > - use variable clock_frame instead of hw_frame
> > - Patch Description exactified
> > snd_usb_us122l (in kernel since .28) needs it, if device is attached to
> > ehci.
> >
> > thanks,
> > Karsten
> >
> >
> >
> > ----------------------------------------------------------------------
> > From: Karsten Wiese <fzu at wemgehoertderstaat.de>
> > Date: Wed, 13 Feb 2008 22:22:09 +0100
> > Subject: [PATCH] USB: Prevent EHCI ITDs reusage while frame is active
> >
> > ITDs can be detached from urbs, before the frame elapses. Now those ITDs are
> > immediately recycled.
> > If the ITD is reused before the frame elapses, the ITD becomes invalid
> > regarding the not yet elapsed frame.
> > Patch takes care of those ITDs by moving them into a new ehci member list
> > cached_itd_list. ITDs resting in cached_itd_list are moved back into their
> > stream's free_list once scan_periodic() detects that the active frame has
> > elapsed.
> >
> > Signed-off-by: Karsten Wiese <fzu at wemgehoertderstaat.de>
> >
> > ---
> > drivers/usb/host/ehci-hcd.c | 2 +
> > drivers/usb/host/ehci-mem.c | 1 +
> > drivers/usb/host/ehci-sched.c | 54 ++++++++++++++++++++++++++++++++++------
> > drivers/usb/host/ehci.h | 5 ++++
> > 4 files changed, 54 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> > index 4725d15..e551bb3 100644
> > --- a/drivers/usb/host/ehci-hcd.c
> > +++ b/drivers/usb/host/ehci-hcd.c
> > @@ -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;
> >
> > @@ -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
> > diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
> > index 0431397..10d5291 100644
> > --- a/drivers/usb/host/ehci-mem.c
> > +++ b/drivers/usb/host/ehci-mem.c
> > @@ -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;
> > diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
> > index a081ee6..c1f7d5f 100644
> > --- a/drivers/usb/host/ehci-sched.c
> > +++ b/drivers/usb/host/ehci-sched.c
> > @@ -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 "
> > @@ -1653,14 +1654,26 @@ 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 still start transactions based on this ITD.
> > + If its content changed that is. Move it to a safe place. */
> > + list_move(&itd->itd_list, &ehci->cached_itd_list);
> > + if (stream->refcount == 2) {
> > + /* If iso_stream_put() would be called here, stream
> > + would be freed. Prevent stream's reusage instead. */
> > + stream->ep->hcpriv = NULL;
> > + stream->ep = NULL;
> > + }
> > + }
> > return retval;
> > }
> >
> > @@ -2101,6 +2114,20 @@ done:
> >
> > /*-------------------------------------------------------------------------*/
> >
> > +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)
> > {
> > @@ -2115,10 +2142,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;
> >
> > @@ -2277,6 +2311,10 @@ restart:
> > /* 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;
> > diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
> > index fb7054c..5262fb7 100644
> > --- a/drivers/usb/host/ehci.h
> > +++ b/drivers/usb/host/ehci.h
> > @@ -86,6 +86,9 @@ struct ehci_hcd { /* one per controller */
> > union ehci_shadow *pshadow; /* mirror hw periodic table */
> > int next_uframe; /* scan periodic, start here */
> > unsigned periodic_sched; /* periodic activity count */
> > + struct list_head cached_itd_list; /* list of itds completed
> > + while frame hadn't yet elapsed */
> > + unsigned clock_frame;
> >
> > /* per root hub port */
> > unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
> > @@ -220,6 +223,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>
--
Philippe Carriere <philippe-f.carriere at wanadoo.fr>
-------------- next part --------------
More information about the Alsa-devel
mailing list