Commit 242f58b9 authored by Johannes Erdfelt's avatar Johannes Erdfelt Committed by Greg Kroah-Hartman

[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
parent f9814887
...@@ -1677,6 +1677,7 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb) ...@@ -1677,6 +1677,7 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
{ {
struct list_head *head, *tmp; struct list_head *head, *tmp;
struct urb_priv *urbp = urb->hcpriv; struct urb_priv *urbp = urb->hcpriv;
int prevactive = 1;
/* We can get called when urbp allocation fails, so check */ /* We can get called when urbp allocation fails, so check */
if (!urbp) if (!urbp)
...@@ -1684,6 +1685,19 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb) ...@@ -1684,6 +1685,19 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ 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; head = &urbp->td_list;
tmp = head->next; tmp = head->next;
while (tmp != head) { while (tmp != head) {
...@@ -1691,15 +1705,18 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb) ...@@ -1691,15 +1705,18 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
tmp = tmp->next; tmp = tmp->next;
/* Control and Isochronous ignore the toggle, so this */ if (!(td->status & TD_CTRL_ACTIVE) &&
/* is safe for all types */ (uhci_actual_length(td->status) < uhci_expected_length(td->info) ||
if ((!(td->status & TD_CTRL_ACTIVE) && tmp == head))
(uhci_actual_length(td->status) < uhci_expected_length(td->info)) ||
tmp == head)) {
usb_settoggle(urb->dev, uhci_endpoint(td->info), usb_settoggle(urb->dev, uhci_endpoint(td->info),
uhci_packetout(td->info), uhci_packetout(td->info),
uhci_toggle(td->info) ^ 1); 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); uhci_delete_queued_urb(uhci, urb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment