All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Brownell <david-b@pacbell.net>
To: linux-usb-devel@lists.sourceforge.net
Cc: Greg KH <greg@kroah.com>, Andrew Morton <akpm@osdl.org>,
	"Carlo E. Prelz" <fluido@fluido.as>,
	linux-kernel@vger.kernel.org
Subject: Re: [linux-usb-devel] Re: ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1
Date: Tue, 24 Jan 2006 07:15:30 -0800	[thread overview]
Message-ID: <200601240715.30368.david-b@pacbell.net> (raw)
In-Reply-To: <20060124044213.GA22270@kroah.com>

[-- 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

  reply	other threads:[~2006-01-24 15:15 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-01-20 12:32 ATI RS480-based motherboard: stuck while booting with kernel >= 2.6.15 rc1 Carlo E. Prelz
2006-01-21  9:09 ` Andrew Morton
2006-01-21 12:57   ` Carlo E. Prelz
2006-01-21 20:58     ` Andrew Morton
2006-01-21 21:28       ` Erwin Rol
2006-01-21 22:04         ` Dave Jones
2006-01-22  4:14           ` Kurt Wall
2006-01-22  7:40       ` Carlo E. Prelz
2006-01-22  7:55         ` Andrew Morton
2006-01-22  8:30           ` Carlo E. Prelz
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
2006-01-23 19:01           ` David Brownell
2006-01-23 21:47             ` Carlo E. Prelz
2006-01-24  4:42             ` Greg KH
2006-01-24 15:15               ` David Brownell [this message]
  -- strict thread matches above, loose matches on Subject: below --
2006-02-07  2:03 Aleksey Gorelov
2006-02-07 22:05 ` David Brownell
2006-02-08  1:04   ` Aleksey V Gorelov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200601240715.30368.david-b@pacbell.net \
    --to=david-b@pacbell.net \
    --cc=akpm@osdl.org \
    --cc=fluido@fluido.as \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.