Commit 2a34f5e6 authored by Eric Anholt's avatar Eric Anholt

drm/i915: Disable GEM when a broken video BIOS takes up the whole aperture.

This is seen on some G41 systems, where the BIOS will consume all but
a few KB of the aperture.  This should be bad for all operating systems, as
it means that the OS can't dynamically manage memory between graphics and
the rest of the system, and OSes that did static memory management
statically add memory in addition to the BIOS allocation anyway.  So, instead
of working around it, just fail out verbosely.

fd.o bug #21574
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
Reviewed-by: default avatarIan Romanick <ian.d.romanick@intel.com>
parent e99da35f
...@@ -885,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, ...@@ -885,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
* some RAM for the framebuffer at early boot. This code figures out * some RAM for the framebuffer at early boot. This code figures out
* how much was set aside so we can use it for our own purposes. * how much was set aside so we can use it for our own purposes.
*/ */
static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
unsigned long *preallocated_size) uint32_t *preallocated_size)
{ {
struct pci_dev *bridge_dev; struct pci_dev *bridge_dev;
u16 tmp = 0; u16 tmp = 0;
...@@ -984,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, ...@@ -984,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
return 0; return 0;
} }
static int i915_load_modeset_init(struct drm_device *dev) static int i915_load_modeset_init(struct drm_device *dev,
unsigned long prealloc_size,
unsigned long agp_size)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long agp_size, prealloc_size;
int fb_bar = IS_I9XX(dev) ? 2 : 0; int fb_bar = IS_I9XX(dev) ? 2 : 0;
int ret = 0; int ret = 0;
...@@ -1002,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -1002,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (IS_I965G(dev) || IS_G33(dev)) if (IS_I965G(dev) || IS_G33(dev))
dev_priv->cursor_needs_physical = false; dev_priv->cursor_needs_physical = false;
ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
if (ret)
goto out;
/* Basic memrange allocator for stolen space (aka vram) */ /* Basic memrange allocator for stolen space (aka vram) */
drm_mm_init(&dev_priv->vram, 0, prealloc_size); drm_mm_init(&dev_priv->vram, 0, prealloc_size);
...@@ -1136,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1136,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
resource_size_t base, size; resource_size_t base, size;
int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
uint32_t agp_size, prealloc_size;
/* i915 has 4 more counters */ /* i915 has 4 more counters */
dev->counters += 4; dev->counters += 4;
...@@ -1184,9 +1182,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1184,9 +1182,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
"performance may suffer.\n"); "performance may suffer.\n");
} }
ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
if (ret)
goto out_iomapfree;
/* enable GEM by default */ /* enable GEM by default */
dev_priv->has_gem = 1; dev_priv->has_gem = 1;
if (prealloc_size > agp_size * 3 / 4) {
DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
"memory stolen.\n",
prealloc_size / 1024, agp_size / 1024);
DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
"updating the BIOS to fix).\n");
dev_priv->has_gem = 0;
}
dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
if (IS_G4X(dev) || IS_IGDNG(dev)) { if (IS_G4X(dev) || IS_IGDNG(dev)) {
...@@ -1231,7 +1242,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1231,7 +1242,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
} }
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_load_modeset_init(dev); ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to init modeset\n"); DRM_ERROR("failed to init modeset\n");
goto out_rmmap; goto out_rmmap;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment