Hi again.
My word, I've put some hours into this, but I now have a 2.6.10 kernel with
which the built-in USB port on my Compaq Armada 7400 works. So far that is, I
want to do a bit more work on fine tuning the duration of the delays I have
added to host/ohci-q.c::finish_unlinks() - 5 millseconds only works some of
the time, 10 milliseconds seems to work all of the time. The patch is
attached and I would be grateful if someone would look it over and ensure
that it is basically OK.
>
> To track that down you should look mostly at the first patch, since you
> know that's what changed things. Remembering that the logic there
> works on essentially all newer chips, you'll have to imagine you're a
> crotchety old bit of hardware that probably wants to be told something
> extra, or maybe be told the same thing but just a bit later.
>
... a bit later was what held the key. I think I am correct in adding mdelays
rather than msleeps, because finish_unlinks is called in interrupt context.
As coded at the moment though, all ohci controllers would be subjected to
these delays, which would be unnecessary with more up-to-date silicon. The
only way i can think of avoiding this is to wrap the code in ifdefs (say
CONFIG_USB_ZFMICRO) and add the appropriate stuff to host/Kconfig. Is that
the right way to go please or have I missed something? For instance, is there
a better way of handling this for a machine had a mix of ancient and modern,
as is the case here (ancient built-in controller, modern on cardbus adapter,
but both ohci). Personally, I'm not too bothered, I'm just pleased to have
the built-in USB working, but some folks like to get every last drop of speed
out of their computers and if watching the kenel development mailing list has
taught me anything, it is that the lengths kernel hackers will go to for the
best solution to a problem is almost boundless :)
All this assumes of course, that my fix is (not flawed and) worth adding to
the code base. During my very early search for a fix, I exchanged email with
two other Armada 7400 users who have experienced this problem. Additionally,
and perhaps most importantly, these old laptops are, as I understand it,
typical of the machines that are being recycled for use by less fortunate
people all over the world, so IMHO it would be worthwhile. I guess it up to
you guys though, if I need to maintain my own patch, so be it.
Regards,
Chris
--- linux-2.6.10-orig/drivers/usb/core/message.c 2004-12-24 21:34:26.000000000 +0000
+++ linux-2.6.10/drivers/usb/core/message.c 2005-02-19 21:44:17.000000000 +0000
@@ -95,6 +95,9 @@
if (!urb)
return -ENOMEM;
+ /* give old and slow silicon a little extra time */
+ msleep(3);
+
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
len, usb_api_blocking_completion, NULL);
--- linux-2.6.10-orig/drivers/usb/host/ohci-q.c 2004-12-24 21:35:28.000000000 +0000
+++ linux-2.6.10/drivers/usb/host/ohci-q.c 2005-02-19 21:43:25.000000000 +0000
@@ -1031,6 +1031,8 @@
}
}
if (ohci->ed_bulktail) {
+ /* give old and slow silicon a little time */
+ mdelay(10);
command |= OHCI_BLF;
if (!(ohci->hc_control & OHCI_CTRL_BLE)) {
control |= OHCI_CTRL_BLE;
@@ -1042,6 +1044,8 @@
/* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
if (control) {
ohci->hc_control |= control;
+ /* give old and slow silicon a little time */
+ mdelay(10);
ohci_writel (ohci, ohci->hc_control,
&ohci->regs->control);
}