I guess (and hope) you plan to soon integrate the last alsa-driver-1.0.18rc3 modules. I alerted the alsa devel team (http://mailman.alsa-project.org/pipermail/alsa-devel/2008-October/011349.html) that the usb ehci-hcd module has to patched in order to have snd-usb-us122l module (the driver for the Tascam US-122l, USB 2.0 soundcard) to work. Unfortunately, the corresponding patch is not yet integrated to linux kernel and is not scheduled until 2.6.28 or still later.
>From mid-june 2008, I provided, on my personal website, patched kernel for Fedora 9 (including patched ehci-hcd and part of what became alsa-driver-1.0.18rc3) under 2.6.25 and presently 2.6.26 kernel for support of Tascam US-122L. Now, an official integration in Fedora would be the better way for standart users.
So the first question is: do you plan to integrate alsa-driver-1.0.18rc3 modules and if so, when ?
The next question is: which way you imagine for integrating the ehci-hcd patch ? Directly adding the patch in kernel packaging (as I do) or providing an alternative module (I am not very usual with the method to do so) ?
I enclose the patch I just successly tested with rawhide Fedora 10 beta. Note that this version is almost the same than the one I sent to alsa-devel, essentially fitting exactly the line numbering.
Regards
Phil.
diff -uNrp linux-2.6.27.x86_64.orig/drivers/usb/host/ehci.h linux-2.6.27.x86_64.new/drivers/usb/host/ehci.h --- linux-2.6.27.x86_64.orig/drivers/usb/host/ehci.h 2008-10-18 15:25:40.000000000 +0200 +++ linux-2.6.27.x86_64.new/drivers/usb/host/ehci.h 2008-10-18 15:26:48.000000000 +0200 @@ -86,6 +86,9 @@ struct ehci_hcd { /* one per controlle 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 hw_frame; /* per root hub port */ unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; @@ -208,6 +211,9 @@ timer_action (struct ehci_hcd *ehci, enu } } +static void free_cached_itd_list(struct ehci_hcd *ehci); + + /*-------------------------------------------------------------------------*/ /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ diff -uNrp linux-2.6.27.x86_64.orig/drivers/usb/host/ehci-hcd.c linux-2.6.27.x86_64.new/drivers/usb/host/ehci-hcd.c --- linux-2.6.27.x86_64.orig/drivers/usb/host/ehci-hcd.c 2008-10-18 15:25:40.000000000 +0200 +++ linux-2.6.27.x86_64.new/drivers/usb/host/ehci-hcd.c 2008-10-18 15:26:48.000000000 +0200 @@ -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->hw_frame = -1; /* * dedicate a qh for the async ring head, since we couldn't unlink diff -uNrp linux-2.6.27.x86_64.orig/drivers/usb/host/ehci-mem.c linux-2.6.27.x86_64.new/drivers/usb/host/ehci-mem.c --- linux-2.6.27.x86_64.orig/drivers/usb/host/ehci-mem.c 2008-10-18 15:25:40.000000000 +0200 +++ linux-2.6.27.x86_64.new/drivers/usb/host/ehci-mem.c 2008-10-18 15:26:48.000000000 +0200 @@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_q 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 -uNrp linux-2.6.27.x86_64.orig/drivers/usb/host/ehci-sched.c linux-2.6.27.x86_64.new/drivers/usb/host/ehci-sched.c --- linux-2.6.27.x86_64.orig/drivers/usb/host/ehci-sched.c 2008-10-18 15:25:40.000000000 +0200 +++ linux-2.6.27.x86_64.new/drivers/usb/host/ehci-sched.c 2008-10-18 15:26:48.000000000 +0200 @@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, st 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,13 +1654,25 @@ 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->hw_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,10 +2114,24 @@ 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) { - unsigned now_uframe, frame, clock, clock_frame, mod; + unsigned frame, hw_frame, clock, clock_frame, now_uframe, mod; unsigned modified; mod = ehci->periodic_size << 3; @@ -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 + hw_frame = (clock >> 3) % ehci->periodic_size; + } else { clock = now_uframe + mod - 1; + hw_frame = -1; + } + if (ehci->hw_frame != hw_frame) { + free_cached_itd_list(ehci); + ehci->hw_frame = hw_frame; + } clock %= mod; clock_frame = clock >> 3; @@ -2277,6 +2311,11 @@ restart: /* rescan the rest of this frame, then ... */ clock = now; clock_frame = clock >> 3; + hw_frame = (clock >> 3); + if (ehci->hw_frame != hw_frame) { + free_cached_itd_list(ehci); + ehci->hw_frame = hw_frame; + } } else { now_uframe++; now_uframe %= mod;
-- fedora-devel-list mailing list fedora-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/fedora-devel-list