# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.378   -> 1.379  
#	  drivers/usb/uhci.c	1.24    -> 1.25   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/02/20	johannes@erdfelt.com	1.379
# [PATCH] uhci.c, one more toggle fix
#  
# This patch fixes another toggle bug and reverts the previous bogus
# patch which caused compile warnings.
# 
# It also adds a quick comment explaining the criteria.
# 
# JE
# --------------------------------------------
#
diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c
--- a/drivers/usb/uhci.c	Wed Feb 20 16:55:40 2002
+++ b/drivers/usb/uhci.c	Wed Feb 20 16:55:40 2002
@@ -1677,6 +1677,7 @@
 {
 	struct list_head *head, *tmp;
 	struct urb_priv *urbp = urb->hcpriv;
+	int prevactive = 1;
 
 	/* We can get called when urbp allocation fails, so check */
 	if (!urbp)
@@ -1684,6 +1685,19 @@
 
 	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
 
+	/*
+	 * Now we need to find out what the last successful toggle was
+	 * so we can update the local data toggle for the next transfer
+	 *
+	 * There's 3 way's the last successful completed TD is found:
+	 *
+	 * 1) The TD is NOT active and the actual length < expected length
+	 * 2) The TD is NOT active and it's the last TD in the chain
+	 * 3) The TD is active and the previous TD is NOT active
+	 *
+	 * Control and Isochronous ignore the toggle, so this is safe
+	 * for all types
+	 */
 	head = &urbp->td_list;
 	tmp = head->next;
 	while (tmp != head) {
@@ -1691,15 +1705,18 @@
 
 		tmp = tmp->next;
 
-		/* Control and Isochronous ignore the toggle, so this */
-		/* is safe for all types */
-		if ((!(td->status & TD_CTRL_ACTIVE) &&
-		    (uhci_actual_length(td->status) < uhci_expected_length(td->info)) ||
-		    tmp == head)) {
+		if (!(td->status & TD_CTRL_ACTIVE) &&
+		    (uhci_actual_length(td->status) < uhci_expected_length(td->info) ||
+		    tmp == head))
 			usb_settoggle(urb->dev, uhci_endpoint(td->info),
 				uhci_packetout(td->info),
 				uhci_toggle(td->info) ^ 1);
-		}
+		else if ((td->status & TD_CTRL_ACTIVE) && !prevactive)
+			usb_settoggle(urb->dev, uhci_endpoint(td->info),
+				uhci_packetout(td->info),
+				uhci_toggle(td->info));
+
+		prevactive = td->status & TD_CTRL_ACTIVE;
 	}
 
 	uhci_delete_queued_urb(uhci, urb);
