[PATCH] bug with EHCI cpufreq patch on nVidia controllers

<[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <DFEF91B22ED07447AB6AA4B237F913F9B18D92@ausx3mpc125.aus.amer.dell.com>
This patch fixes a bug with the cpu frequency change notifier and nVidia
EHCI controllers.  The nVidia controllers write the transfer overlay
back to the qtd when they see the "inactivate" bit set in the qh, which
clears the "active" bit in qtd->hw_token.  When the qh was reactivated,
the "active" bit in the overlay's hw_token was turned back on, but not
the one in the qtd.  This caused qh_completions to think that qtd was
finished even though it wasn't.

This patch (against 2.6.23-rc1) fixes this bug.

Signed-off-by: Stuart Hayes <[email protected]>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
ehci_cpufreq_nvidia_30july_b.patch (application/octet-stream, 1.3 KB)
--- linux-2.6.22-rc1-mm1-orig/drivers/usb/host/ehci-sched.c	2007-07-30 06:07:11.000000000 -0500
+++ linux-2.6.22-rc1-mm1/drivers/usb/host/ehci-sched.c	2007-07-30 08:39:54.000000000 -0500
@@ -547,6 +547,19 @@ static void qh_inactivate_split_intr_qhs
 	wmb();
 }
 
+static inline struct ehci_qtd *current_qtd (struct ehci_qh *qh)
+{
+	struct list_head	*entry, *tmp;
+	struct ehci_qtd		*qtd;
+
+	list_for_each_safe (entry, tmp, &qh->qtd_list) {
+		qtd = list_entry (entry, struct ehci_qtd, qtd_list);
+		if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current)
+			return qtd;
+	}
+	return NULL;
+}
+
 static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci)
 {
 	struct ehci_qh	*qh;
@@ -566,12 +579,21 @@ static void qh_reactivate_split_intr_qhs
 			if (safe == 0) {
 				not_done = 1;
 			} else if (safe > 0) {
+				struct ehci_qtd *qtd;
+
 				/* See EHCI 1.0 section 4.15.2.4. */
+				qtd = current_qtd(qh);	
 				token = qh->hw_token;
 				qh->hw_token = (token | HALT_BIT) & ~ACTIVE_BIT;
 				wmb();
 				qh->hw_info1 &= ~INACTIVATE_BIT;
 				wmb();
+				/*
+				 * nVidia controllers write overlay back to qtd
+				 * when qh is inactivated, so reactivate it too.
+				 */
+				if (qtd)
+					qtd->hw_token = token | qh->was_active;
 				qh->hw_token = (token & ~HALT_BIT) | qh->was_active;
 			}
 		}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.