ChangeSet 1.1305.7.5, 2003/06/16 12:01:45-07:00, david-b@pacbell.net [PATCH] USB: ehci, fix qh re-activation problem This resolves a problem that appears when relinking a bulk or control QH that has a partially completed multi-packet qTD. Some I/O could be repeated. Such cases can happen when an empty QH starts to unlink, but gets re-activated (by queueing the multi-packet qTD) before the HC saw the unlink. It's rarely an issue with control traffic (transfers are so small) or when bulk queues are active (the QH won't empty). drivers/usb/host/ehci-hcd.c | 2 +- drivers/usb/host/ehci-q.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c Wed Jun 18 11:15:55 2003 +++ b/drivers/usb/host/ehci-hcd.c Wed Jun 18 11:15:55 2003 @@ -91,7 +91,7 @@ * 2001-June Works with usb-storage and NEC EHCI on 2.4 */ -#define DRIVER_VERSION "2003-Jun-12" +#define DRIVER_VERSION "2003-Jun-13" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Wed Jun 18 11:15:55 2003 +++ b/drivers/usb/host/ehci-q.c Wed Jun 18 11:15:55 2003 @@ -360,11 +360,17 @@ if (unlikely (stopped != 0) /* some EHCI 0.95 impls will overlay dummy qtds */ || qh->hw_qtd_next == EHCI_LIST_END) { - qh_update (ehci, qh, - list_empty (&qh->qtd_list) - ? qh->dummy - : list_entry (qh->qtd_list.next, - struct ehci_qtd, qtd_list)); + if (list_empty (&qh->qtd_list)) + end = qh->dummy; + else { + end = list_entry (qh->qtd_list.next, + struct ehci_qtd, qtd_list); + /* first qtd may already be partially processed */ + if (cpu_to_le32 (end->qtd_dma) == qh->hw_current) + end = 0; + } + if (end) + qh_update (ehci, qh, end); } return count;