mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* RE: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
@ 2006-02-07  2:03 Aleksey Gorelov
  2006-02-07 22:05 ` David Brownell
  0 siblings, 1 reply; 13+ messages in thread
From: Aleksey Gorelov @ 2006-02-07  2:03 UTC (permalink / raw)
  To: David Brownell, linux-usb-devel
  Cc: Andrew Morton, Carlo E. Prelz, linux-kernel

Hi Dave,

>-----Original Message-----
>From: linux-kernel-owner@vger.kernel.org 
>[mailto:linux-kernel-owner@vger.kernel.org] On Behalf Of David Brownell
>Sent: Monday, January 23, 2006 11:01 AM
>To: linux-usb-devel@lists.sourceforge.net
>Cc: Andrew Morton; Carlo E. Prelz; linux-kernel@vger.kernel.org
>Subject: Re: [linux-usb-devel] Re: ATI RS480-based 
>motherboard: stuck while booting with kernel >= 2.6.15 rc1
>
>
>> OK, so it sounds like quirk_usb_disable_ehci() caused your 
>machine to hang
>> with the old BIOS.  That's fairly bad behaviour from the kernel, even
>> though the BIOS presumably had some problems.
>
>I think what happened is the "always run quirks" code got turned into
>the default too early, before the EHCI "quirk" version of the handoff
>code got checked against what most systems have been using for the past
>several years.
>
>I noticed at least one suspicous thing:  it enables an SMI IRQ.

  As far as I recall, some BIOSes can be stuck at handoff forever
waiting for SMI if this is not enabled. No doubt BIOS bug, and seems
like work around brakes some other systems, grrr...

>Even in cases when the boot firmware says it's not using EHCI ...
  That's what I do not understand. SOOE is enabled only if BIOS ownes
EHCI - check for ECHI_USBLEGSUP_BIOS in previous 'if' statement. Am I
missing something ?

Thanks,
Aleks.

>easy to imagine that causing hangage.
>
>
>Maybe this time it'd help to tell your BIOS "yes, DO use USB".
>Or, the attached patch might help.  Please try both experiments.
>
>- Dave
>
>
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-07  2:03 [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1 Aleksey Gorelov
@ 2006-02-07 22:05 ` David Brownell
  2006-02-08  1:04   ` Aleksey V Gorelov
  0 siblings, 1 reply; 13+ messages in thread
From: David Brownell @ 2006-02-07 22:05 UTC (permalink / raw)
  To: linux-usb-devel
  Cc: Aleksey Gorelov, Andrew Morton, Carlo E. Prelz, linux-kernel

On Monday 06 February 2006 6:03 pm, Aleksey Gorelov wrote:
> Hi Dave,
> 
> >....
> >
> >I think what happened is the "always run quirks" code got turned into
> >the default too early, before the EHCI "quirk" version of the handoff
> >code got checked against what most systems have been using for the past
> >several years.
> >
> >I noticed at least one suspicous thing:  it enables an SMI IRQ.
> 
>   As far as I recall, some BIOSes can be stuck at handoff forever
> waiting for SMI if this is not enabled. No doubt BIOS bug, and seems
> like work around brakes some other systems, grrr...

I gathered as much and that's why I preserved that behavior.

But it would be nice to know _which_ BIOS versions have that bug;
it's clearly a BIOS bug, and given the other problems we've seen,
it might be better to have that "turn on the SMI" be keyed by some
"real" quirk logic or kernel parameters.

(The fact that USB handoff is being driven by "quirk" logic, even
when it's not a quirk, also raises little warning flags...)


> >Even in cases when the boot firmware says it's not using EHCI ...
>
>   That's what I do not understand. SOOE is enabled only if BIOS ownes
> EHCI - check for ECHI_USBLEGSUP_BIOS in previous 'if' statement. Am I
> missing something ?

That's how it works now, but it didn't do that before.  Previously it
always turned on the SMI, and then never turned it off, causing issues
on various platforms.

Of course, the BIOS that Carlo is struggling with seems terminally
broken, and is blatantly ignoring the spec for how those handoff
flags are supposed to work.

- Dave



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-07 22:05 ` David Brownell
@ 2006-02-08  1:04   ` Aleksey V Gorelov
  0 siblings, 0 replies; 13+ messages in thread
From: Aleksey V Gorelov @ 2006-02-08  1:04 UTC (permalink / raw)
  To: David Brownell
  Cc: linux-usb-devel, Andrew Morton, Carlo E. Prelz, linux-kernel

On Tue, 2006-02-07 at 14:05 -0800, David Brownell wrote:
> On Monday 06 February 2006 6:03 pm, Aleksey Gorelov wrote:
> > Hi Dave,
> > 
> > >....
> > >
> > >I think what happened is the "always run quirks" code got turned into
> > >the default too early, before the EHCI "quirk" version of the handoff
> > >code got checked against what most systems have been using for the past
> > >several years.
> > >
> > >I noticed at least one suspicous thing:  it enables an SMI IRQ.
> > 
> >   As far as I recall, some BIOSes can be stuck at handoff forever
> > waiting for SMI if this is not enabled. No doubt BIOS bug, and seems
> > like work around brakes some other systems, grrr...
> 
> I gathered as much and that's why I preserved that behavior.
> 
> But it would be nice to know _which_ BIOS versions have that bug;
> it's clearly a BIOS bug, and given the other problems we've seen,
> it might be better to have that "turn on the SMI" be keyed by some
> "real" quirk logic or kernel parameters.

  Agree with this. At the time the code was written I did not run into
any issues with it, hence it was the default. Unfortunately, I do not
remember exact platforms. (yes, platforms, not BIOS versions -
unfortunately, lots of bugs are introduced during tailoring BIOS to
particular platform). 

> 
> (The fact that USB handoff is being driven by "quirk" logic, even
> when it's not a quirk, also raises little warning flags...)

Frankly, we are still not doing it early enough. On some platforms it
causes huge delays during some of ACPI code, and quirks are working
afterward... Moving handoff earlier resolves the issue, but this may be
a bit of extreme...

> 
> 
> > >Even in cases when the boot firmware says it's not using EHCI ...
> >
> >   That's what I do not understand. SOOE is enabled only if BIOS ownes
> > EHCI - check for ECHI_USBLEGSUP_BIOS in previous 'if' statement. Am I
> > missing something ?
> 
> That's how it works now, but it didn't do that before.  Previously it
> always turned on the SMI, and then never turned it off, causing issues
> on various platforms.

No, it's been like this all the time. Compare 'switch' and 'if'
statements in the patch against single original 'if' but with 2
conditions. Your patch is actually different in the following ways:
- it goes over all possible capabilities instead of processing just
first one - right thing to do;
- it always sets OS ownership, even if BIOS did not have it.
- it always disables SMI, not just in case when handoff failed. This
probably right way to cleanup after BIOS which does handoff, but does
not disable SMI afterward.

  In other words, it does stop doing what previous code was doing, it
just extends it. And according to Greg, it extends it in right way ;-)

> 
> Of course, the BIOS that Carlo is struggling with seems terminally
> broken, and is blatantly ignoring the spec for how those handoff
> flags are supposed to work.

Agree.

Aleks.

> 
> - Dave
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-06 17:31             ` David Brownell
@ 2006-02-06 17:45               ` Carlo E. Prelz
  0 siblings, 0 replies; 13+ messages in thread
From: Carlo E. Prelz @ 2006-02-06 17:45 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-usb-devel, Andrew Morton, linux-kernel

	Subject: Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
	Date: Mon 06 Feb 06 09:31:14AM -0800

Quoting David Brownell (david-b@pacbell.net):

> Then if disabling that code which enables the SMI doesn't work,
> you have only one real option other than telling your BIOS not
> to support USB keyboards/mice/disks:  replace your BIOS.

Sapphire has no newer bios than the one I am using. But I am saying
that USB works with that line commented out. I tried a couple of USB
disks, a USB mouse and my palm pilot - all seem to work quite OK. No
angry messages.

Carlo

-- 
  *         Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as             che bisogno ci sarebbe
  *               di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-06 16:50           ` Carlo E. Prelz
@ 2006-02-06 17:31             ` David Brownell
  2006-02-06 17:45               ` Carlo E. Prelz
  0 siblings, 1 reply; 13+ messages in thread
From: David Brownell @ 2006-02-06 17:31 UTC (permalink / raw)
  To: linux-usb-devel; +Cc: Carlo E. Prelz, Andrew Morton, linux-kernel


> > If it printed that, then how is it possible that it hung _before_ printing
> > that message???
> 
> I already wrote that I had commented out the line that caused the
> hangup:
> 
> //			pci_write_config_byte(pdev, offset + 3, 1);
> 
> After commenting out this line, the machine boots OK and EHCI works
> fine. It does print the BIOS handoff failed message. 

Then if disabling that code which enables the SMI doesn't work,
you have only one real option other than telling your BIOS not
to support USB keyboards/mice/disks:  replace your BIOS.

The reason it prints the BIOS handoff message is because you
completely disabled the handoff, so your BIOS still thinks it
owns that controller.  Commenting out that line is not good.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-06 16:24         ` David Brownell
@ 2006-02-06 16:50           ` Carlo E. Prelz
  2006-02-06 17:31             ` David Brownell
  0 siblings, 1 reply; 13+ messages in thread
From: Carlo E. Prelz @ 2006-02-06 16:50 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-usb-devel, Andrew Morton, linux-kernel

	Subject: Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
	Date: Mon 06 Feb 06 08:24:04AM -0800

Quoting David Brownell (david-b@pacbell.net):

> If it printed that, then how is it possible that it hung _before_ printing
> that message???

I already wrote that I had commented out the line that caused the
hangup:

//			pci_write_config_byte(pdev, offset + 3, 1);

After commenting out this line, the machine boots OK and EHCI works
fine. It does print the BIOS handoff failed message. 

If I do not comment out the above line, the machine hangs, and,
obviously, no BIOS handoff failed message is printed.

Carlo

-- 
  *         Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as             che bisogno ci sarebbe
  *               di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-06  8:02       ` Carlo E. Prelz
@ 2006-02-06 16:24         ` David Brownell
  2006-02-06 16:50           ` Carlo E. Prelz
  0 siblings, 1 reply; 13+ messages in thread
From: David Brownell @ 2006-02-06 16:24 UTC (permalink / raw)
  To: Carlo E. Prelz; +Cc: linux-usb-devel, Andrew Morton, linux-kernel

On Monday 06 February 2006 12:02 am, Carlo E. Prelz wrote:
> 
> > Interesting ... feels like a BIOS problem.  If you want to experiment,
> > there's a right bracket -- "}" -- immediately before that.  Try moving
> > it right after that write, so that write_config_byte is covered by the
> > preceding "if LEGSUP_BIOS" test; or copying the much later "disable SMI"
> > clause into an "else" for that "if".
> 
> The first one would be useless - I inserted lots of printouts to find
> out where the freeze took place, and I know that the 
> EHCI_USBLEGSUP_BIOS flag is on (cap is 0x10001). The value remains the
> same after the 'spin till it hands it over' loop - so that this
> printout appears:
> 
> 0000:00:13.2 EHCI: BIOS handoff failed (BIOS bug ?)

If it printed that, then how is it possible that it hung _before_ printing
that message???  Your reports are not making any sense to me.

Maybe that whole "if" block that turns that SMI _on_ is the problem; it
was part of the "early handoff" code, which came from who knows where,
was clearly buggy, and was never widely used until recently.  Enabling
the SMI seemed pretty dubious to me, but I suspect that some undescribed
buggy BIOS really does need it ... maybe whoever provided that "early"
handoff version could report what they were trying to do by enabling
the SMI?

- Dave


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-05 19:45     ` [linux-usb-devel] " David Brownell
@ 2006-02-06  8:02       ` Carlo E. Prelz
  2006-02-06 16:24         ` David Brownell
  0 siblings, 1 reply; 13+ messages in thread
From: Carlo E. Prelz @ 2006-02-06  8:02 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-usb-devel, Andrew Morton, linux-kernel

	Subject: Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
	Date: dom 05 feb 06 11:45:22 -0800

Quoting David Brownell (david-b@pacbell.net):

> Interesting ... feels like a BIOS problem.  If you want to experiment,
> there's a right bracket -- "}" -- immediately before that.  Try moving
> it right after that write, so that write_config_byte is covered by the
> preceding "if LEGSUP_BIOS" test; or copying the much later "disable SMI"
> clause into an "else" for that "if".

The first one would be useless - I inserted lots of printouts to find
out where the freeze took place, and I know that the 
EHCI_USBLEGSUP_BIOS flag is on (cap is 0x10001). The value remains the
same after the 'spin till it hands it over' loop - so that this
printout appears:

0000:00:13.2 EHCI: BIOS handoff failed (BIOS bug ?)

About the second thing you suggest: do you refer to this call?

			/* just in case, always disable EHCI SMIs */
			pci_write_config_dword(pdev,
					offset + EHCI_USBLEGCTLSTS,
					0);

In my machine, the write takes place without apparent ill effects. If
I add it as an else clause to the "if LEGSUP_BIOS" test, it won't
execute, because the EHCI_USBLEGSUP_BIOS flag is on.

In case you need it: hcc_params is 0xa012. 

Carlo

-- 
  *         Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as             che bisogno ci sarebbe
  *               di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-02-05 10:33   ` Carlo E. Prelz
@ 2006-02-05 19:45     ` David Brownell
  2006-02-06  8:02       ` Carlo E. Prelz
  0 siblings, 1 reply; 13+ messages in thread
From: David Brownell @ 2006-02-05 19:45 UTC (permalink / raw)
  To: linux-usb-devel; +Cc: Carlo E. Prelz, Andrew Morton, linux-kernel

On Sunday 05 February 2006 2:33 am, Carlo E. Prelz wrote:
> In drivers/usb/host/pci-quirks.c, in function quirk_usb_disable_ehci
> (should start around line 211) there is a stanza that reads:
> 
> 			/* always say Linux will own the hardware
> 			 * by setting EHCI_USBLEGSUP_OS.
> 			 */
> 			pci_write_config_byte(pdev, offset + 3, 1);
> 
> On my sapphire athlon64 motherboard (see the thread for more details),
> this call never returns (without generating any output). I commented
> it out, and now the EHCI subsystem works OK (currently running
> 2.6.16rc2).

Interesting ... feels like a BIOS problem.  If you want to experiment,
there's a right bracket -- "}" -- immediately before that.  Try moving
it right after that write, so that write_config_byte is covered by the
preceding "if LEGSUP_BIOS" test; or copying the much later "disable SMI"
clause into an "else" for that "if".

- Dave

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-01-24  4:42       ` Greg KH
@ 2006-01-24 15:15         ` David Brownell
  0 siblings, 0 replies; 13+ messages in thread
From: David Brownell @ 2006-01-24 15:15 UTC (permalink / raw)
  To: linux-usb-devel; +Cc: Greg KH, Andrew Morton, Carlo E. Prelz, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1036 bytes --]

On Monday 23 January 2006 8:42 pm, Greg KH wrote:
> On Mon, Jan 23, 2006 at 11:01:25AM -0800, David Brownell wrote:
> > This moves the previously widely-used ehci-pci.c BIOS handoff
> > code into the pci-quirks.c file, replacing the less widely used
> > "early handoff" version that seems to cause problems lately.
> > 
> > One notable change:  the "early handoff" version always enabled
> > an SMI IRQ ... and did so even if the pre-Linux code said it was
> > not using EHCI (and not expecting EHCI SMIs).  Looks like a goof
> > in a workaround for some unknown BIOS version.
> > 
> > This merged version only forcibly enables those IRQs when pre-Linux
> > code says it's using EHCI.  And now it always forces them off "just
> > in case".
> 
> Thanks for posting this, it fixes my EHCI + APIC error, and makes my
> laptop work just fine.

OK, here's a version with a Signed-Off-By; against current GIT.

I'm mildly surprised it helps that laptop, but not surprised that
it helps _some_ of those "ehci init goofs" cases.  :)

- Dave




[-- Attachment #2: ehci-handoff.patch --]
[-- Type: text/x-diff, Size: 7297 bytes --]

This moves the previously widely-used ehci-pci.c BIOS handoff
code into the pci-quirks.c file, replacing the less widely used
"early handoff" version that seems to cause problems lately.

One notable change:  the "early handoff" version always enabled
an SMI IRQ ... and did so even if the pre-Linux code said it was
not using EHCI (and not expecting EHCI SMIs).  Looks like a goof
in a workaround for some unknown BIOS version.

This merged version only forcibly enables those IRQs when pre-Linux
code says it's using EHCI.  And now it always forces them off "just
in case".

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>

Index: g26/drivers/usb/host/ehci-pci.c
===================================================================
--- g26.orig/drivers/usb/host/ehci-pci.c	2006-01-15 12:59:13.000000000 -0800
+++ g26/drivers/usb/host/ehci-pci.c	2006-01-22 09:17:54.000000000 -0800
@@ -24,40 +24,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
- */
-static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap)
-{
-	struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
-	/* always say Linux will own the hardware */
-	pci_write_config_byte(pdev, where + 3, 1);
-
-	/* maybe wait a while for BIOS to respond */
-	if (cap & (1 << 16)) {
-		int msec = 5000;
-
-		do {
-			msleep(10);
-			msec -= 10;
-			pci_read_config_dword(pdev, where, &cap);
-		} while ((cap & (1 << 16)) && msec);
-		if (cap & (1 << 16)) {
-			ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
-				where, cap);
-			// some BIOS versions seem buggy...
-			// return 1;
-			ehci_warn(ehci, "continuing after BIOS bug...\n");
-			/* disable all SMIs, and clear "BIOS owns" flag */
-			pci_write_config_dword(pdev, where + 4, 0);
-			pci_write_config_byte(pdev, where + 2, 0);
-		} else
-			ehci_dbg(ehci, "BIOS handoff succeeded\n");
-	}
-	return 0;
-}
-
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
 {
@@ -84,32 +50,9 @@ static int ehci_pci_reinit(struct ehci_h
 		}
 	}
 
-	temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params));
-
-	/* EHCI 0.96 and later may have "extended capabilities" */
-	while (temp && count--) {
-		u32		cap;
-
-		pci_read_config_dword(pdev, temp, &cap);
-		ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp);
-		switch (cap & 0xff) {
-		case 1:			/* BIOS/SMM/... handoff */
-			if (bios_handoff(ehci, temp, cap) != 0)
-				return -EOPNOTSUPP;
-			break;
-		case 0:			/* illegal reserved capability */
-			ehci_dbg(ehci, "illegal capability!\n");
-			cap = 0;
-			/* FALLTHROUGH */
-		default:		/* unknown */
-			break;
-		}
-		temp = (cap >> 8) & 0xff;
-	}
-	if (!count) {
-		ehci_err(ehci, "bogus capabilities ... PCI problems!\n");
-		return -EIO;
-	}
+	/* we expect static quirk code to handle the "extended capabilities"
+	 * (currently just BIOS handoff) allowed starting with EHCI 0.96
+	 */
 
 	/* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
 	retval = pci_set_mwi(pdev);
Index: g26/drivers/usb/host/pci-quirks.c
===================================================================
--- g26.orig/drivers/usb/host/pci-quirks.c	2006-01-05 17:35:38.000000000 -0800
+++ g26/drivers/usb/host/pci-quirks.c	2006-01-22 11:20:52.000000000 -0800
@@ -190,7 +190,7 @@ static void __devinit quirk_usb_handoff_
 			msleep(10);
 		}
 		if (wait_time <= 0)
-			printk(KERN_WARNING "%s %s: early BIOS handoff "
+			printk(KERN_WARNING "%s %s: BIOS handoff "
 					"failed (BIOS bug ?)\n",
 					pdev->dev.bus_id, "OHCI");
 
@@ -212,8 +212,9 @@ static void __devinit quirk_usb_disable_
 {
 	int wait_time, delta;
 	void __iomem *base, *op_reg_base;
-	u32 hcc_params, val, temp;
-	u8 cap_length;
+	u32	hcc_params, val;
+	u8	offset, cap_length;
+	int	count = 256/4;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -224,51 +225,80 @@ static void __devinit quirk_usb_disable_
 
 	cap_length = readb(base);
 	op_reg_base = base + cap_length;
+
+	/* EHCI 0.96 and later may have "extended capabilities"
+	 * spec section 5.1 explains the bios handoff, e.g. for
+	 * booting from USB disk or using a usb keyboard
+	 */
 	hcc_params = readl(base + EHCI_HCC_PARAMS);
-	hcc_params = (hcc_params >> 8) & 0xff;
-	if (hcc_params) {
-		pci_read_config_dword(pdev,
-					hcc_params + EHCI_USBLEGSUP,
-					&val);
-		if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
-			/*
-			 * Ok, BIOS is in smm mode, try to hand off...
-			 */
-			pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						&temp);
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						temp | EHCI_USBLEGCTLSTS_SOOE);
-			val |= EHCI_USBLEGSUP_OS;
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						val);
+	offset = (hcc_params >> 8) & 0xff;
+	while (offset && count--) {
+		u32		cap;
+		int		msec;
+
+		pci_read_config_dword(pdev, offset, &cap);
+		switch (cap & 0xff) {
+		case 1:			/* BIOS/SMM/... handoff support */
+			if ((cap & EHCI_USBLEGSUP_BIOS)) {
+				pr_debug("%s %s: BIOS handoff\n",
+						pdev->dev.bus_id, "EHCI");
 
-			wait_time = 500;
-			do {
-				msleep(10);
-				wait_time -= 10;
+				/* BIOS workaround (?): be sure the
+				 * pre-Linux code receives the SMI
+				 */
 				pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
+						offset + EHCI_USBLEGCTLSTS,
 						&val);
-			} while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
-			if (!wait_time) {
-				/*
-				 * well, possibly buggy BIOS...
+				pci_write_config_dword(pdev,
+						offset + EHCI_USBLEGCTLSTS,
+						val | EHCI_USBLEGCTLSTS_SOOE);
+			}
+
+			/* always say Linux will own the hardware
+			 * by setting EHCI_USBLEGSUP_OS.
+			 */
+			pci_write_config_byte(pdev, offset + 3, 1);
+
+			/* if boot firmware now owns EHCI, spin till
+			 * it hands it over.
+			 */
+			msec = 5000;
+			while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
+				msleep(10);
+				msec -= 10;
+				pci_read_config_dword(pdev, offset, &cap);
+			}
+
+			if (cap & EHCI_USBLEGSUP_BIOS) {
+				/* well, possibly buggy BIOS... try to shut
+				 * it down, and hope nothing goes too wrong
 				 */
-				printk(KERN_WARNING "%s %s: early BIOS handoff "
+				printk(KERN_WARNING "%s %s: BIOS handoff "
 						"failed (BIOS bug ?)\n",
 					pdev->dev.bus_id, "EHCI");
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						EHCI_USBLEGSUP_OS);
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						0);
+				pci_write_config_byte(pdev, offset + 2, 0);
 			}
+
+			/* just in case, always disable EHCI SMIs */
+			pci_write_config_dword(pdev,
+					offset + EHCI_USBLEGCTLSTS,
+					0);
+			break;
+		case 0:			/* illegal reserved capability */
+			cap = 0;
+			/* FALLTHROUGH */
+		default:
+			printk(KERN_WARNING "%s %s: unrecognized "
+					"capability %02x\n",
+					pdev->dev.bus_id, "EHCI",
+					cap & 0xff);
+			break;
 		}
+		offset = (cap >> 8) & 0xff;
 	}
+	if (!count)
+		printk(KERN_DEBUG "%s %s: capability loop?\n",
+				pdev->dev.bus_id, "EHCI");
 
 	/*
 	 * halt EHCI & disable its interrupts in any case

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-01-23 19:01     ` [linux-usb-devel] " David Brownell
  2006-01-23 21:47       ` Carlo E. Prelz
@ 2006-01-24  4:42       ` Greg KH
  2006-01-24 15:15         ` David Brownell
  1 sibling, 1 reply; 13+ messages in thread
From: Greg KH @ 2006-01-24  4:42 UTC (permalink / raw)
  To: David Brownell
  Cc: linux-usb-devel, Andrew Morton, Carlo E. Prelz, linux-kernel

On Mon, Jan 23, 2006 at 11:01:25AM -0800, David Brownell wrote:
> This moves the previously widely-used ehci-pci.c BIOS handoff
> code into the pci-quirks.c file, replacing the less widely used
> "early handoff" version that seems to cause problems lately.
> 
> One notable change:  the "early handoff" version always enabled
> an SMI IRQ ... and did so even if the pre-Linux code said it was
> not using EHCI (and not expecting EHCI SMIs).  Looks like a goof
> in a workaround for some unknown BIOS version.
> 
> This merged version only forcibly enables those IRQs when pre-Linux
> code says it's using EHCI.  And now it always forces them off "just
> in case".

Thanks for posting this, it fixes my EHCI + APIC error, and makes my
laptop work just fine.

Turns out that 2.6.14 worked for it, but 2.6.15 didn't.  git bisect a
zillion times later narrowed it down to the usb early handoff stuff but
due to merge issues, it was tough to track down the exact patch.

For fun I tried this one on top of the latest -mm, and it works!

So, care to clean it up to make it feel better to you and send it to me
again so I can add it to my tree?  I know the next SuSE kernel will need
it :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-01-23 19:01     ` [linux-usb-devel] " David Brownell
@ 2006-01-23 21:47       ` Carlo E. Prelz
  2006-01-24  4:42       ` Greg KH
  1 sibling, 0 replies; 13+ messages in thread
From: Carlo E. Prelz @ 2006-01-23 21:47 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-usb-devel, Andrew Morton, linux-kernel

	Subject: Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
	Date: lun 23 gen 06 11:01:25 -0800

Quoting David Brownell (david-b@pacbell.net):

> Maybe this time it'd help to tell your BIOS "yes, DO use USB".

That I am doing. And I now have the appropriate OHCI module
loaded. USB 1.1 works apparently quite OK. 

> Or, the attached patch might help.  

I applied the patch. The three changes to the second file applied with
an offset of 6 lines (to 2.6.15 vanilla). Nothing changed: the booting
process hung at the same place, generating the same printout as
before. I have now booted the new kernel with EHCI disabled, and saved
the dmesg oputput to http://www.fluido.as/files/dmesg2.txt (here,
USB1.1 is active).

It is time for sleep for me. I will perform any new test tomorrow
morning.

Carlo


-- 
  *         Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as             che bisogno ci sarebbe
  *               di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
  2006-01-22  7:55   ` Andrew Morton
@ 2006-01-23 19:01     ` David Brownell
  2006-01-23 21:47       ` Carlo E. Prelz
  2006-01-24  4:42       ` Greg KH
  0 siblings, 2 replies; 13+ messages in thread
From: David Brownell @ 2006-01-23 19:01 UTC (permalink / raw)
  To: linux-usb-devel; +Cc: Andrew Morton, Carlo E. Prelz, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 735 bytes --]


> OK, so it sounds like quirk_usb_disable_ehci() caused your machine to hang
> with the old BIOS.  That's fairly bad behaviour from the kernel, even
> though the BIOS presumably had some problems.

I think what happened is the "always run quirks" code got turned into
the default too early, before the EHCI "quirk" version of the handoff
code got checked against what most systems have been using for the past
several years.

I noticed at least one suspicous thing:  it enables an SMI IRQ.
Even in cases when the boot firmware says it's not using EHCI ...
easy to imagine that causing hangage.


Maybe this time it'd help to tell your BIOS "yes, DO use USB".
Or, the attached patch might help.  Please try both experiments.

- Dave



[-- Attachment #2: ehci-handoff.patch --]
[-- Type: text/x-diff, Size: 7247 bytes --]

This moves the previously widely-used ehci-pci.c BIOS handoff
code into the pci-quirks.c file, replacing the less widely used
"early handoff" version that seems to cause problems lately.

One notable change:  the "early handoff" version always enabled
an SMI IRQ ... and did so even if the pre-Linux code said it was
not using EHCI (and not expecting EHCI SMIs).  Looks like a goof
in a workaround for some unknown BIOS version.

This merged version only forcibly enables those IRQs when pre-Linux
code says it's using EHCI.  And now it always forces them off "just
in case".

EXPERIMENTAL


Index: g26/drivers/usb/host/ehci-pci.c
===================================================================
--- g26.orig/drivers/usb/host/ehci-pci.c	2006-01-15 12:59:13.000000000 -0800
+++ g26/drivers/usb/host/ehci-pci.c	2006-01-22 09:17:54.000000000 -0800
@@ -24,40 +24,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
- * off the controller (maybe it can boot from highspeed USB disks).
- */
-static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap)
-{
-	struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
-
-	/* always say Linux will own the hardware */
-	pci_write_config_byte(pdev, where + 3, 1);
-
-	/* maybe wait a while for BIOS to respond */
-	if (cap & (1 << 16)) {
-		int msec = 5000;
-
-		do {
-			msleep(10);
-			msec -= 10;
-			pci_read_config_dword(pdev, where, &cap);
-		} while ((cap & (1 << 16)) && msec);
-		if (cap & (1 << 16)) {
-			ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
-				where, cap);
-			// some BIOS versions seem buggy...
-			// return 1;
-			ehci_warn(ehci, "continuing after BIOS bug...\n");
-			/* disable all SMIs, and clear "BIOS owns" flag */
-			pci_write_config_dword(pdev, where + 4, 0);
-			pci_write_config_byte(pdev, where + 2, 0);
-		} else
-			ehci_dbg(ehci, "BIOS handoff succeeded\n");
-	}
-	return 0;
-}
-
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
 {
@@ -84,32 +50,9 @@ static int ehci_pci_reinit(struct ehci_h
 		}
 	}
 
-	temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params));
-
-	/* EHCI 0.96 and later may have "extended capabilities" */
-	while (temp && count--) {
-		u32		cap;
-
-		pci_read_config_dword(pdev, temp, &cap);
-		ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp);
-		switch (cap & 0xff) {
-		case 1:			/* BIOS/SMM/... handoff */
-			if (bios_handoff(ehci, temp, cap) != 0)
-				return -EOPNOTSUPP;
-			break;
-		case 0:			/* illegal reserved capability */
-			ehci_dbg(ehci, "illegal capability!\n");
-			cap = 0;
-			/* FALLTHROUGH */
-		default:		/* unknown */
-			break;
-		}
-		temp = (cap >> 8) & 0xff;
-	}
-	if (!count) {
-		ehci_err(ehci, "bogus capabilities ... PCI problems!\n");
-		return -EIO;
-	}
+	/* we expect static quirk code to handle the "extended capabilities"
+	 * (currently just BIOS handoff) allowed starting with EHCI 0.96
+	 */
 
 	/* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
 	retval = pci_set_mwi(pdev);
Index: g26/drivers/usb/host/pci-quirks.c
===================================================================
--- g26.orig/drivers/usb/host/pci-quirks.c	2006-01-05 17:35:38.000000000 -0800
+++ g26/drivers/usb/host/pci-quirks.c	2006-01-22 11:20:52.000000000 -0800
@@ -190,7 +190,7 @@ static void __devinit quirk_usb_handoff_
 			msleep(10);
 		}
 		if (wait_time <= 0)
-			printk(KERN_WARNING "%s %s: early BIOS handoff "
+			printk(KERN_WARNING "%s %s: BIOS handoff "
 					"failed (BIOS bug ?)\n",
 					pdev->dev.bus_id, "OHCI");
 
@@ -212,8 +212,9 @@ static void __devinit quirk_usb_disable_
 {
 	int wait_time, delta;
 	void __iomem *base, *op_reg_base;
-	u32 hcc_params, val, temp;
-	u8 cap_length;
+	u32	hcc_params, val;
+	u8	offset, cap_length;
+	int	count = 256/4;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -224,51 +225,80 @@ static void __devinit quirk_usb_disable_
 
 	cap_length = readb(base);
 	op_reg_base = base + cap_length;
+
+	/* EHCI 0.96 and later may have "extended capabilities"
+	 * spec section 5.1 explains the bios handoff, e.g. for
+	 * booting from USB disk or using a usb keyboard
+	 */
 	hcc_params = readl(base + EHCI_HCC_PARAMS);
-	hcc_params = (hcc_params >> 8) & 0xff;
-	if (hcc_params) {
-		pci_read_config_dword(pdev,
-					hcc_params + EHCI_USBLEGSUP,
-					&val);
-		if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
-			/*
-			 * Ok, BIOS is in smm mode, try to hand off...
-			 */
-			pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						&temp);
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						temp | EHCI_USBLEGCTLSTS_SOOE);
-			val |= EHCI_USBLEGSUP_OS;
-			pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						val);
+	offset = (hcc_params >> 8) & 0xff;
+	while (offset && count--) {
+		u32		cap;
+		int		msec;
+
+		pci_read_config_dword(pdev, offset, &cap);
+		switch (cap & 0xff) {
+		case 1:			/* BIOS/SMM/... handoff support */
+			if ((cap & EHCI_USBLEGSUP_BIOS)) {
+				pr_debug("%s %s: BIOS handoff\n",
+						pdev->dev.bus_id, "EHCI");
 
-			wait_time = 500;
-			do {
-				msleep(10);
-				wait_time -= 10;
+				/* BIOS workaround (?): be sure the
+				 * pre-Linux code receives the SMI
+				 */
 				pci_read_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
+						offset + EHCI_USBLEGCTLSTS,
 						&val);
-			} while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
-			if (!wait_time) {
-				/*
-				 * well, possibly buggy BIOS...
+				pci_write_config_dword(pdev,
+						offset + EHCI_USBLEGCTLSTS,
+						val | EHCI_USBLEGCTLSTS_SOOE);
+			}
+
+			/* always say Linux will own the hardware
+			 * by setting EHCI_USBLEGSUP_OS.
+			 */
+			pci_write_config_byte(pdev, offset + 3, 1);
+
+			/* if boot firmware now owns EHCI, spin till
+			 * it hands it over.
+			 */
+			msec = 5000;
+			while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
+				msleep(10);
+				msec -= 10;
+				pci_read_config_dword(pdev, offset, &cap);
+			}
+
+			if (cap & EHCI_USBLEGSUP_BIOS) {
+				/* well, possibly buggy BIOS... try to shut
+				 * it down, and hope nothing goes too wrong
 				 */
-				printk(KERN_WARNING "%s %s: early BIOS handoff "
+				printk(KERN_WARNING "%s %s: BIOS handoff "
 						"failed (BIOS bug ?)\n",
 					pdev->dev.bus_id, "EHCI");
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGSUP,
-						EHCI_USBLEGSUP_OS);
-				pci_write_config_dword(pdev,
-						hcc_params + EHCI_USBLEGCTLSTS,
-						0);
+				pci_write_config_byte(pdev, offset + 2, 0);
 			}
+
+			/* just in case, always disable EHCI SMIs */
+			pci_write_config_dword(pdev,
+					offset + EHCI_USBLEGCTLSTS,
+					0);
+			break;
+		case 0:			/* illegal reserved capability */
+			cap = 0;
+			/* FALLTHROUGH */
+		default:
+			printk(KERN_WARNING "%s %s: unrecognized "
+					"capability %02x\n",
+					pdev->dev.bus_id, "EHCI",
+					cap & 0xff);
+			break;
 		}
+		offset = (cap >> 8) & 0xff;
 	}
+	if (!count)
+		printk(KERN_DEBUG "%s %s: capability loop?\n",
+				pdev->dev.bus_id, "EHCI");
 
 	/*
 	 * halt EHCI & disable its interrupts in any case

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2006-02-08  1:04 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-02-07  2:03 [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1 Aleksey Gorelov
2006-02-07 22:05 ` David Brownell
2006-02-08  1:04   ` Aleksey V Gorelov
  -- strict thread matches above, loose matches on Subject: below --
2006-01-20 12:32 Carlo E. Prelz
2006-01-22  7:40 ` Carlo E. Prelz
2006-01-22  7:55   ` Andrew Morton
2006-01-23 19:01     ` [linux-usb-devel] " David Brownell
2006-01-23 21:47       ` Carlo E. Prelz
2006-01-24  4:42       ` Greg KH
2006-01-24 15:15         ` David Brownell
2006-01-22 11:11 ` Carlo E. Prelz
2006-02-05 10:33   ` Carlo E. Prelz
2006-02-05 19:45     ` [linux-usb-devel] " David Brownell
2006-02-06  8:02       ` Carlo E. Prelz
2006-02-06 16:24         ` David Brownell
2006-02-06 16:50           ` Carlo E. Prelz
2006-02-06 17:31             ` David Brownell
2006-02-06 17:45               ` Carlo E. Prelz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome