On Saturday 04 September 2004 9:00 am, Alan Stern wrote:
> Messages like this, devoted to programming issues, generally belong on the
> linux-usb-devel mailing list. Relatively few developers follow
> linux-usb-users.
>
> Alan Stern
>
> P.S.: Have you checked to see whether this problem has already been
> resolved in 2.6.9-rc1?
Or more particularly by RC1 plus
http://marc.theaimsgroup.com/?l=linux-usb-devel&m=109417418826995&w=2
That patch makes a minor change in the periodic reinit logic.
I suspect it won't matter for the bug pacman found, but the
patch attached here _should_ matter.
> Date: Fri, 3 Sep 2004 21:44:16 -0500 (EST)
> From: [EMAIL PROTECTED]
> Subject: [Linux-usb-users] OHCI bug introduced in 2.6.7-rc1
>
> ...
> SiS OHCI controller
> ...
>
> ... I found that the difference comes from the
> following line:
>
> temp = ohci_readl (&ohci->regs->fminterval);
>
> On the first module load, temp is 0xbff82edf. On the
> second module load, it is 0x00002edf.
The driver was misusing those high bits. It always needs
to initialize them, while it's the low bits that can be saved.
Please try the attached patch.
> ...
> This was a rough one...
Yeah, I've had to chase fminterval bugs before too. Oddly
enough, also on SiS (and sometimes OPTi) hardware.
- Dave
A recent patch to make OHCI initialization work better with local clocks
that aren't quite standard didn't work right. The result was transfers
failing inconsistently on some systems. This patch makes that register
initialization behave more correctly.
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
--- 1.77/drivers/usb/host/ohci-hcd.c Wed Sep 1 15:45:39 2004
+++ edited/drivers/usb/host/ohci-hcd.c Sat Sep 4 10:56:01 2004
@@ -409,11 +409,19 @@
/* boot firmware should have set this up (5.1.1.3.1) */
if (!ohci->fminterval) {
+ u32 t2;
+
temp = ohci_readl (&ohci->regs->fminterval);
- if (temp & 0x3fff0000)
- ohci->fminterval = temp;
- else
- ohci->fminterval = DEFAULT_FMINTERVAL;
+ ohci->fminterval = temp & 0x3fff;
+ if (ohci->fminterval != FI)
+ ohci_dbg (ohci, "fminterval delta %d\n",
+ ohci->fminterval - FI);
+
+ t2 = FSMP (ohci->fminterval);
+ temp >>= 16;
+ if ((t2/2) < temp || temp > t2)
+ temp = t2;
+ ohci->fminterval |= temp << 16;
/* also: power/overcurrent flags in roothub.a */
}
--- 1.32/drivers/usb/host/ohci.h Wed Sep 1 15:45:39 2004
+++ edited/drivers/usb/host/ohci.h Sat Sep 4 10:59:02 2004
@@ -406,13 +406,14 @@
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
-#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
+#define FSMP(fi) ((6 * ((fi) - 210)) / 7)
#define LSTHRESH 0x628 /* lowspeed bit threshold */
static inline void periodic_reinit (struct ohci_hcd *ohci)
{
+ u32 fi = ohci->fminterval & 0x0ffff;
writel (ohci->fminterval, &ohci->regs->fminterval);
- writel (((9 * FI) / 10) & 0x3fff, &ohci->regs->periodicstart);
+ writel (((9 * fi) / 10) & 0x3fff, &ohci->regs->periodicstart);
writel (LSTHRESH, &ohci->regs->lsthresh);
}
--- 1.31/drivers/usb/host/ohci-dbg.c Thu Jul 15 07:13:38 2004
+++ edited/drivers/usb/host/ohci-dbg.c Sat Sep 4 10:22:14 2004
@@ -640,14 +640,14 @@
rdata = ohci_readl (®s->fminterval);
temp = scnprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
- rdata, (rdata >> 31) ? " FIT" : "",
+ rdata, (rdata >> 31) ? "FIT " : "",
(rdata >> 16) & 0xefff, rdata & 0xffff);
size -= temp;
next += temp;
rdata = ohci_readl (®s->fmremaining);
temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
- rdata, (rdata >> 31) ? " FRT" : "",
+ rdata, (rdata >> 31) ? "FRT " : "",
rdata & 0x3fff);
size -= temp;
next += temp;