ehci-hcd patch for alsa-driver-1.0.18rc3 snd-usb-us122l module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Fedora Announce]     [Fedora Kernel]     [Fedora Testing]     [Fedora Formulas]     [Fedora PHP Devel]     [Kernel Development]     [Fedora Legacy]     [Fedora Maintainers]     [Fedora Desktop]     [PAM]     [Red Hat Development]     [Gimp]     [Yosemite News]
  Powered by Linux