[patch 4/5] USB: ehci: microframe handling fix

2005-08-04 Thread Greg KH
From: David Brownell <[EMAIL PROTECTED]>

This patch has a one line oops fix, plus related cleanups.

 - The bugfix uses microframe scheduling data given to the hardware to
   test "is this a periodic QH", rather than testing for nonzero period.
   (Prevents an oops by providing the correct answer.)

 - The cleanup going along with the patch should make it clearer what's
   going on whenever those bitfields are accessed.

The bug came about when, around January, two new kinds of EHCI interrupt
scheduling operation were added, involving both the high speed (24 KBytes
per millisec) and low/full speed (1-64 bytes per millisec) microframe
scheduling.  A driver for the Edirol UA-1000 Audio Capture Unit ran into
the oops; it used one of the newly supported high speed modes.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
 drivers/usb/host/ehci-dbg.c   |2 +-
 drivers/usb/host/ehci-q.c |5 +++--
 drivers/usb/host/ehci-sched.c |   13 +++--
 drivers/usb/host/ehci.h   |5 +
 4 files changed, 16 insertions(+), 9 deletions(-)

--- gregkh-2.6.orig/drivers/usb/host/ehci-dbg.c 2005-08-04 17:37:11.0 
-0700
+++ gregkh-2.6/drivers/usb/host/ehci-dbg.c  2005-08-04 17:40:08.0 
-0700
@@ -527,7 +527,7 @@
p.qh->period,
le32_to_cpup (>hw_info2)
/* uframe masks */
-   & 0x,
+   & (QH_CMASK | QH_SMASK),
p.qh);
size -= temp;
next += temp;
--- gregkh-2.6.orig/drivers/usb/host/ehci.h 2005-08-04 17:37:11.0 
-0700
+++ gregkh-2.6/drivers/usb/host/ehci.h  2005-08-04 17:40:08.0 -0700
@@ -385,6 +385,11 @@
__le32  hw_info1;/* see EHCI 3.6.2 */
 #defineQH_HEAD 0x8000
__le32  hw_info2;/* see EHCI 3.6.2 */
+#defineQH_SMASK0x00ff
+#defineQH_CMASK0xff00
+#defineQH_HUBADDR  0x007f
+#defineQH_HUBPORT  0x3f80
+#defineQH_MULT 0xc000
__le32  hw_current;  /* qtd list - see EHCI 3.6.4 */

/* qtd overlay (hardware parts of a struct ehci_qtd) */
--- gregkh-2.6.orig/drivers/usb/host/ehci-q.c   2005-08-04 17:37:11.0 
-0700
+++ gregkh-2.6/drivers/usb/host/ehci-q.c2005-08-04 17:40:08.0 
-0700
@@ -222,7 +222,7 @@
struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
 
/* S-mask in a QH means it's an interrupt urb */
-   if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
+   if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
 
/* ... update hc-wide periodic stats (for usbfs) */
ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -428,7 +428,8 @@
/* should be rare for periodic transfers,
 * except maybe high bandwidth ...
 */
-   if (qh->period) {
+   if ((__constant_cpu_to_le32 (QH_SMASK)
+   & qh->hw_info2) != 0) {
intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
} else
--- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c   2005-08-04 
17:37:11.0 -0700
+++ gregkh-2.6/drivers/usb/host/ehci-sched.c2005-08-04 17:40:08.0 
-0700
@@ -301,7 +301,7 @@
 
dev_dbg (>dev->dev,
"link qh%d-%04x/%p start %d [%d/%d us]\n",
-   period, le32_to_cpup (>hw_info2) & 0x,
+   period, le32_to_cpup (>hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
 
/* high bandwidth, or otherwise every microframe */
@@ -385,7 +385,8 @@
 
dev_dbg (>dev->dev,
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
-   qh->period, le32_to_cpup (>hw_info2) & 0x,
+   qh->period,
+   le32_to_cpup (>hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
 
/* qh->qh_next still "live" to HC */
@@ -411,7 +412,7 @@
 * active high speed queues may need bigger delays...
 */
if (list_empty (>qtd_list)
-   || (__constant_cpu_to_le32 (0x0ff << 8)
+   || (__constant_cpu_to_le32 (QH_CMASK)
& qh->hw_info2) != 0)
wait = 2;
else
@@ 

[patch 4/5] USB: ehci: microframe handling fix

2005-08-04 Thread Greg KH
From: David Brownell [EMAIL PROTECTED]

This patch has a one line oops fix, plus related cleanups.

 - The bugfix uses microframe scheduling data given to the hardware to
   test is this a periodic QH, rather than testing for nonzero period.
   (Prevents an oops by providing the correct answer.)

 - The cleanup going along with the patch should make it clearer what's
   going on whenever those bitfields are accessed.

The bug came about when, around January, two new kinds of EHCI interrupt
scheduling operation were added, involving both the high speed (24 KBytes
per millisec) and low/full speed (1-64 bytes per millisec) microframe
scheduling.  A driver for the Edirol UA-1000 Audio Capture Unit ran into
the oops; it used one of the newly supported high speed modes.

Signed-off-by: David Brownell [EMAIL PROTECTED]
Signed-off-by: Andrew Morton [EMAIL PROTECTED]
Signed-off-by: Greg Kroah-Hartman [EMAIL PROTECTED]

---
 drivers/usb/host/ehci-dbg.c   |2 +-
 drivers/usb/host/ehci-q.c |5 +++--
 drivers/usb/host/ehci-sched.c |   13 +++--
 drivers/usb/host/ehci.h   |5 +
 4 files changed, 16 insertions(+), 9 deletions(-)

--- gregkh-2.6.orig/drivers/usb/host/ehci-dbg.c 2005-08-04 17:37:11.0 
-0700
+++ gregkh-2.6/drivers/usb/host/ehci-dbg.c  2005-08-04 17:40:08.0 
-0700
@@ -527,7 +527,7 @@
p.qh-period,
le32_to_cpup (p.qh-hw_info2)
/* uframe masks */
-0x,
+(QH_CMASK | QH_SMASK),
p.qh);
size -= temp;
next += temp;
--- gregkh-2.6.orig/drivers/usb/host/ehci.h 2005-08-04 17:37:11.0 
-0700
+++ gregkh-2.6/drivers/usb/host/ehci.h  2005-08-04 17:40:08.0 -0700
@@ -385,6 +385,11 @@
__le32  hw_info1;/* see EHCI 3.6.2 */
 #defineQH_HEAD 0x8000
__le32  hw_info2;/* see EHCI 3.6.2 */
+#defineQH_SMASK0x00ff
+#defineQH_CMASK0xff00
+#defineQH_HUBADDR  0x007f
+#defineQH_HUBPORT  0x3f80
+#defineQH_MULT 0xc000
__le32  hw_current;  /* qtd list - see EHCI 3.6.4 */

/* qtd overlay (hardware parts of a struct ehci_qtd) */
--- gregkh-2.6.orig/drivers/usb/host/ehci-q.c   2005-08-04 17:37:11.0 
-0700
+++ gregkh-2.6/drivers/usb/host/ehci-q.c2005-08-04 17:40:08.0 
-0700
@@ -222,7 +222,7 @@
struct ehci_qh  *qh = (struct ehci_qh *) urb-hcpriv;
 
/* S-mask in a QH means it's an interrupt urb */
-   if ((qh-hw_info2  __constant_cpu_to_le32 (0x00ff)) != 0) {
+   if ((qh-hw_info2  __constant_cpu_to_le32 (QH_SMASK)) != 0) {
 
/* ... update hc-wide periodic stats (for usbfs) */
ehci_to_hcd(ehci)-self.bandwidth_int_reqs--;
@@ -428,7 +428,8 @@
/* should be rare for periodic transfers,
 * except maybe high bandwidth ...
 */
-   if (qh-period) {
+   if ((__constant_cpu_to_le32 (QH_SMASK)
+qh-hw_info2) != 0) {
intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
} else
--- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c   2005-08-04 
17:37:11.0 -0700
+++ gregkh-2.6/drivers/usb/host/ehci-sched.c2005-08-04 17:40:08.0 
-0700
@@ -301,7 +301,7 @@
 
dev_dbg (qh-dev-dev,
link qh%d-%04x/%p start %d [%d/%d us]\n,
-   period, le32_to_cpup (qh-hw_info2)  0x,
+   period, le32_to_cpup (qh-hw_info2)  (QH_CMASK | QH_SMASK),
qh, qh-start, qh-usecs, qh-c_usecs);
 
/* high bandwidth, or otherwise every microframe */
@@ -385,7 +385,8 @@
 
dev_dbg (qh-dev-dev,
unlink qh%d-%04x/%p start %d [%d/%d us]\n,
-   qh-period, le32_to_cpup (qh-hw_info2)  0x,
+   qh-period,
+   le32_to_cpup (qh-hw_info2)  (QH_CMASK | QH_SMASK),
qh, qh-start, qh-usecs, qh-c_usecs);
 
/* qh-qh_next still live to HC */
@@ -411,7 +412,7 @@
 * active high speed queues may need bigger delays...
 */
if (list_empty (qh-qtd_list)
-   || (__constant_cpu_to_le32 (0x0ff  8)
+   || (__constant_cpu_to_le32 (QH_CMASK)
 qh-hw_info2) != 0)
wait = 2;
else
@@ -533,7 +534,7 @@
 
/*