All of lore.kernel.org
 help / color / mirror / Atom feed
From: Woody Suwalski <woodys@xandros.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>,
	jbarnes@virtuousgeek.org, eric@anholt.net,
	intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	torvalds@linux-foundation.org, stable@kernel.org
Subject: Re: Intel 915GM MCHBAR bug
Date: Fri, 5 Jun 2009 17:09:05 -0400	[thread overview]
Message-ID: <4A298971.5080006@xandros.com> (raw)
In-Reply-To: <20090605130033.5ff3d0b5.akpm@linux-foundation.org>

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

Andrew Morton wrote:
> On Fri, 05 Jun 2009 11:02:21 +0300
> Pekka Enberg <penberg@cs.helsinki.fi> wrote:
>
>   
>> Hi Jesse,
>>
>> (I am cc'ing linux-kernel.)
>>
>> On Mon, 01 Jun 2009 22:31:13 +0300
>>     
>>> Pekka Enberg <penberg@cs.helsinki.fi> wrote:
>>>
>>>       
>>>> Hi Jesse,
>>>>
>>>> I am seeing this on my Eee PC 701 which is running a Ubuntu 
>>>> 2.6.28-11.42-generic stock kernel:
>>>>
>>>> [   76.826966] [drm:i915_gem_detect_bit_6_swizzle] *ERROR* Couldn't
>>>> read from MCHBAR.  Disabling tiling.
>>>> [   76.827215] [drm] Initialized i915 1.6.0 20080730 on minor 0
>>>> [   76.834037] [drm:i915_setparam] *ERROR* unknown parameter 4
>>>> [   76.834104] [drm:i915_getparam] *ERROR* Unknown parameter 6
>>>>
>>>> Google turned up this patch
>>>>
>>>> http://lists.freedesktop.org/archives/intel-gfx/2009-January/001186.html
>>>>
>>>> but I don't seem to find it mainline kernel.
>>>>
>>>> Was the bug fixed in some other way? It seem that distributions have
>>>> not yet picked up your patch and I am unsure if it's in any of the
>>>> -stable kernels.
>>>>         
>> On Thu, 2009-06-04 at 11:27 +0100, Jesse Barnes wrote:
>>     
>>> I think Eric acked it but may not have pushed it to drm-intel-next
>>> yet.  Should happen in the next week or two though as we prepare the
>>> merge window series.
>>>       
>> OK, thanks for the info! FYI, I tested 2.6.30-rc8 with your patch
>> applied and everything works smoothly on my EeePC 701. I did not test
>> plain 2.6.30-rc8 as I expect it to show same kind of behavior as Ubuntu
>> distro kernel. Is this correct or do you want me to test 2.6.30-rc8 too?
>>
>> I wonder why the patch hasn't received more attention as it's a pretty
>> critical bug. The _default_ Ubuntu 9.04 netbook remix installation is
>> completely broken for EeePC 701 (and probably others as well) without
>> the patch. And it's not as if I'm the only one that suffers from it. A
>> quick Google search reveals that a lot of people are hitting it.
>>
>> So I really do think we need to merge this patch to the upcoming 2.6.31
>> ASAP and backport it to -stable after it has gotten some more testing.
>>
>>     
>
> Wanna show us the patch?
>
> Because the world could certainly do with more i915 bugfixes :(
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>   
Here is Jesse's patch from 
http://lists.freedesktop.org/archives/intel-gfx/2009-January/001186.html 
adopted for 2.6.30-rc8... (needed to redo hunk #3 for i915_gem_tile.c)

Woody

-- 
Woody Suwalski, Xandros, Ottawa, Canada, 1-613-842-3498 x414


[-- Attachment #2: i915_tile.patch.txt --]
[-- Type: text/plain, Size: 6325 bytes --]

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9851589..5919537 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -143,6 +143,8 @@ typedef struct drm_i915_private {
 	drm_local_map_t hws_map;
 	struct drm_gem_object *hws_obj;
 
+	struct resource mch_res;
+
 	unsigned int cpp;
 	int back_offset;
 	int front_offset;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c 
b/drivers/gpu/drm/i915/i915_gem_tiling.c
index fe7877a..1441a9e 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -24,6 +24,7 @@
  *    Eric Anholt <eric@anholt.net>
  *
  */
+#include <linux/acpi.h>
 
 #include "linux/string.h"
 #include "linux/bitops.h"
@@ -81,6 +82,176 @@
  * to match what the GPU expects.
  */
 
+#define MCHBAR_I915 0x44
+#define MCHBAR_I965 0x48
+#define MCHBAR_SIZE (4*4096)
+
+#define DEVEN_REG 0x54
+#define   DEVEN_MCHBAR_EN (1 << 28)
+
+/*
+ * ACPI resource checking fun.  So the MCHBAR has *probably* been set
+ * up by the BIOS since drivers need to poke at it, but out of paranoia
+ * or whatever, many BIOSes disable the MCHBAR at boot.  So we check
+ * to make sure any existing address is reserved before using it.  If
+ * we can't find a match or there is no address, allocate some new PCI
+ * space for it, and then enable it.  And of course 915 has to be different
+ * and put its enable bit somewhere else...
+ */
+static acpi_status __init check_mch_resource(struct acpi_resource *res,
+					     void *data)
+{
+	struct resource *mch_res = data;
+	struct acpi_resource_address64 address;
+	acpi_status status;
+
+	if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+		struct acpi_resource_fixed_memory32 *fixmem32 =
+			&res->data.fixed_memory32;
+		if (!fixmem32)
+			return AE_OK;
+
+		if ((mch_res->start >= fixmem32->address) &&
+		    (mch_res->end < (fixmem32->address +
+				      fixmem32->address_length))) {
+			mch_res->flags = 1;
+			return AE_CTRL_TERMINATE;
+		}
+	}
+	if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
+	    (res->type != ACPI_RESOURCE_TYPE_ADDRESS64))
+		return AE_OK;
+
+	status = acpi_resource_to_address64(res, &address);
+	if (ACPI_FAILURE(status) ||
+	   (address.address_length <= 0) ||
+	   (address.resource_type != ACPI_MEMORY_RANGE))
+		return AE_OK;
+
+	if ((mch_res->start >= address.minimum) &&
+	    (mch_res->end < (address.minimum + address.address_length))) {
+		mch_res->flags = 1;
+		return AE_CTRL_TERMINATE;
+	}
+	return AE_OK;
+}
+
+static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
+					       void *context, void **rv)
+{
+	struct resource *mch_res = context;
+
+	acpi_walk_resources(handle, METHOD_NAME__CRS,
+			    check_mch_resource, context);
+
+	if (mch_res->flags)
+		return AE_CTRL_TERMINATE;
+
+	return AE_OK;
+}
+
+static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
+{
+	struct resource mch_res;
+
+	mch_res.start = start;
+	mch_res.end = end;
+	mch_res.flags = 0;
+
+	acpi_get_devices("PNP0C01", find_mboard_resource, &mch_res, NULL);
+
+	if (!mch_res.flags)
+		acpi_get_devices("PNP0C02", find_mboard_resource, &mch_res,
+				 NULL);
+
+	return mch_res.flags;
+}
+
+/* Allocate space for the MCH regs if needed, return nonzero on error */
+static int
+intel_alloc_mchbar_resource(struct drm_device *dev)
+{
+	struct pci_dev *bridge_dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp_lo, temp_hi = 0;
+	u64 mchbar_addr;
+	int ret;
+
+	bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	if (!bridge_dev) {
+		DRM_DEBUG("no bridge dev?!\n");
+		return -ENODEV;
+	}
+
+	if (IS_I965G(dev))
+		pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
+	pci_read_config_dword(bridge_dev, reg, &temp_lo);
+	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
+
+	/* If ACPI doesn't have it, assume we need to allocate it ourselves */
+	if (mchbar_addr &&
+	    is_acpi_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE, 0))
+		return 0;
+
+	/* Get some space for it */
+	ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
+				     MCHBAR_SIZE, MCHBAR_SIZE,
+				     PCIBIOS_MIN_MEM,
+				     0,   pcibios_align_resource,
+				     bridge_dev);
+	if (ret) {
+		DRM_DEBUG("failed bus alloc: %d\n", ret);
+		dev_priv->mch_res.start = 0;
+		return ret;
+	}
+
+	if (IS_I965G(dev))
+		pci_write_config_dword(bridge_dev, reg + 4,
+				       upper_32_bits(dev_priv->mch_res.start));
+
+	pci_write_config_dword(bridge_dev, reg,
+			       lower_32_bits(dev_priv->mch_res.start));
+
+	return 0;
+}
+
+static void
+intel_setup_mchbar(struct drm_device *dev)
+{
+	struct pci_dev *bridge_dev;
+	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp;
+
+	bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+	if (!bridge_dev) {
+		DRM_DEBUG("no bridge dev?!\n");
+		return;
+	}
+
+	if (intel_alloc_mchbar_resource(dev))
+		return;
+
+	/* Now enable it */
+	if (IS_I915G(dev) || IS_I915GM(dev)) {
+		pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
+		pci_write_config_dword(bridge_dev, DEVEN_REG,
+				       temp | DEVEN_MCHBAR_EN);
+	} else {
+		pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
+		pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
+	}
+}
+
+static void
+intel_teardown_mchbar(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (dev_priv->mch_res.start)
+		release_resource(&dev_priv->mch_res);
+}
+
 /**
  * Detects bit 6 swizzling of address lookup between IGD access and CPU
  * access through main memory.
@@ -101,6 +272,9 @@ i915_gem_detect_bit_6_swizzle(struct drm
 	} else if (IS_MOBILE(dev)) {
 		uint32_t dcc;
 
+    		/* Try to make sure MCHBAR is enabled before poking at it */
+		intel_setup_mchbar(dev);
+
 		/* On mobile 9xx chipsets, channel interleave by the CPU is
 		 * determined by DCC.  For single-channel, neither the CPU
 		 * nor the GPU do swizzling.  For dual channel interleaved,
@@ -140,6 +314,8 @@ i915_gem_detect_bit_6_swizzle(struct drm
 			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 		}
+
+		intel_teardown_mchbar(dev);
 	} else {
 		/* The 965, G33, and newer, have a very flexible memory
 		 * configuration.  It will enable dual-channel mode

  reply	other threads:[~2009-06-05 21:17 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <4A242C81.6020906@cs.helsinki.fi>
     [not found] ` <20090604112738.4c01d35e@jbarnes-x200>
2009-06-05  8:02   ` Intel 915GM MCHBAR bug Pekka Enberg
2009-06-05 20:00     ` Andrew Morton
2009-06-05 21:09       ` Woody Suwalski [this message]
2009-06-06  6:14         ` Pekka Enberg
2009-06-06  6:27           ` Andrew Morton
2009-06-06  6:37             ` Pekka Enberg
2009-06-06 20:27               ` Jesse Barnes
2009-06-09 22:07                 ` [Intel-gfx] " Jesse Barnes
2009-06-09 22:28                   ` Andrew Morton
2009-06-29 17:33                     ` [stable] " Greg KH
2009-06-29 18:27                       ` Greg KH
2009-06-29 18:51                         ` Ozan Çağlayan
2009-06-29 20:45                           ` Greg KH
2009-06-06 22:58               ` Andy Whitcroft

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=4A298971.5080006@xandros.com \
    --to=woodys@xandros.com \
    --cc=akpm@linux-foundation.org \
    --cc=eric@anholt.net \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jbarnes@virtuousgeek.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=penberg@cs.helsinki.fi \
    --cc=stable@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /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.