Commit a4de0526 authored by Daniel Vetter's avatar Daniel Vetter

drm/i915: Kick out vga console

Touching the VGA resources on an IVB EFI machine causes hard hangs when
we then kick out the efifb. Ouch.

Apparently this also prevents unclaimed register errors on hsw and
hard machine hangs on my i855gm when trying to unbind fbcon.

Also, we want this to make I915_FBDEV=n safe.

v2: Rebase and pimp commit message.

v3: We also need to unregister the vga console, otherwise the unbind
of the fb console before module unload might resurrect it again.

v4: Ignore errors when the vga console is already unregistered - this
can happen when e.g. reloading i915.ko.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: linux-fbdev@vger.kernel.org
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (v1)
Reviewed-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Acked-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 4c2e0990
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/console.h>
#include <linux/vt.h>
#include <linux/vgaarb.h> #include <linux/vgaarb.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pnp.h> #include <linux/pnp.h>
...@@ -1449,6 +1451,38 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) ...@@ -1449,6 +1451,38 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
} }
#endif #endif
#if !defined(CONFIG_VGA_CONSOLE)
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
return 0;
}
#elif !defined(CONFIG_DUMMY_CONSOLE)
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
return -ENODEV;
}
#else
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
{
int ret;
DRM_INFO("Replacing VGA console driver\n");
console_lock();
ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
if (ret == 0) {
ret = do_unregister_con_driver(&vga_con);
/* Ignore "already unregistered". */
if (ret == -ENODEV)
ret = 0;
}
console_unlock();
return ret;
}
#endif
static void i915_dump_device_info(struct drm_i915_private *dev_priv) static void i915_dump_device_info(struct drm_i915_private *dev_priv)
{ {
const struct intel_device_info *info = &dev_priv->info; const struct intel_device_info *info = &dev_priv->info;
...@@ -1622,8 +1656,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1622,8 +1656,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (ret) if (ret)
goto out_regs; goto out_regs;
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_kick_out_vgacon(dev_priv);
if (ret) {
DRM_ERROR("failed to remove conflicting VGA console\n");
goto out_gtt;
}
i915_kick_out_firmware_fb(dev_priv); i915_kick_out_firmware_fb(dev_priv);
}
pci_set_master(dev->pdev); pci_set_master(dev->pdev);
......
...@@ -77,3 +77,4 @@ const struct consw dummy_con = { ...@@ -77,3 +77,4 @@ const struct consw dummy_con = {
.con_set_palette = DUMMY, .con_set_palette = DUMMY,
.con_scrolldelta = DUMMY, .con_scrolldelta = DUMMY,
}; };
EXPORT_SYMBOL_GPL(dummy_con);
...@@ -1440,5 +1440,6 @@ const struct consw vga_con = { ...@@ -1440,5 +1440,6 @@ const struct consw vga_con = {
.con_build_attr = vgacon_build_attr, .con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region, .con_invert_region = vgacon_invert_region,
}; };
EXPORT_SYMBOL(vga_con);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
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