소스 검색

Merge remote-tracking branch 'drm-intel/topic/kicking-dogs-and-vgacon' into drm-intel-fixes

vt/vgacon fixes to avoid hangs, unclaimed register errors on module
load, reload:

vt: Fix replacement console check when unbinding
vt: Fix up unregistration of vt drivers
vt: Don't ignore unbind errors in vt_unbind
drm/i915: Fixup global gtt cleanup
drm/i915: Kick out vga console

Link: http://lkml.kernel.org/r/1401980308-5116-1-git-send-email-daniel.vetter@ffwll.ch
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Jani Nikula 11 년 전
부모
커밋
ce9557b9fe
5개의 변경된 파일66개의 추가작업 그리고 16개의 파일을 삭제
  1. 42 5
      drivers/gpu/drm/i915/i915_dma.c
  2. 8 1
      drivers/gpu/drm/i915/i915_gem_gtt.c
  3. 14 10
      drivers/tty/vt/vt.c
  4. 1 0
      drivers/video/console/dummycon.c
  5. 1 0
      drivers/video/console/vgacon.c

+ 42 - 5
drivers/gpu/drm/i915/i915_dma.c

@@ -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>
@@ -1386,7 +1388,6 @@ cleanup_gem:
 	i915_gem_context_fini(dev);
 	i915_gem_context_fini(dev);
 	mutex_unlock(&dev->struct_mutex);
 	mutex_unlock(&dev->struct_mutex);
 	WARN_ON(dev_priv->mm.aliasing_ppgtt);
 	WARN_ON(dev_priv->mm.aliasing_ppgtt);
-	drm_mm_takedown(&dev_priv->gtt.base.mm);
 cleanup_irq:
 cleanup_irq:
 	drm_irq_uninstall(dev);
 	drm_irq_uninstall(dev);
 cleanup_gem_stolen:
 cleanup_gem_stolen:
@@ -1450,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;
@@ -1623,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);
 
 
@@ -1756,8 +1796,6 @@ out_mtrrfree:
 	arch_phys_wc_del(dev_priv->gtt.mtrr);
 	arch_phys_wc_del(dev_priv->gtt.mtrr);
 	io_mapping_free(dev_priv->gtt.mappable);
 	io_mapping_free(dev_priv->gtt.mappable);
 out_gtt:
 out_gtt:
-	list_del(&dev_priv->gtt.base.global_link);
-	drm_mm_takedown(&dev_priv->gtt.base.mm);
 	dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
 	dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
 out_regs:
 out_regs:
 	intel_uncore_fini(dev);
 	intel_uncore_fini(dev);
@@ -1846,7 +1884,6 @@ int i915_driver_unload(struct drm_device *dev)
 			i915_free_hws(dev);
 			i915_free_hws(dev);
 	}
 	}
 
 
-	list_del(&dev_priv->gtt.base.global_link);
 	WARN_ON(!list_empty(&dev_priv->vm_list));
 	WARN_ON(!list_empty(&dev_priv->vm_list));
 
 
 	drm_vblank_cleanup(dev);
 	drm_vblank_cleanup(dev);

+ 8 - 1
drivers/gpu/drm/i915/i915_gem_gtt.c

@@ -1992,7 +1992,10 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
 
 
 	struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
 	struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
 
 
-	drm_mm_takedown(&vm->mm);
+	if (drm_mm_initialized(&vm->mm)) {
+		drm_mm_takedown(&vm->mm);
+		list_del(&vm->global_link);
+	}
 	iounmap(gtt->gsm);
 	iounmap(gtt->gsm);
 	teardown_scratch_page(vm->dev);
 	teardown_scratch_page(vm->dev);
 }
 }
@@ -2025,6 +2028,10 @@ static int i915_gmch_probe(struct drm_device *dev,
 
 
 static void i915_gmch_remove(struct i915_address_space *vm)
 static void i915_gmch_remove(struct i915_address_space *vm)
 {
 {
+	if (drm_mm_initialized(&vm->mm)) {
+		drm_mm_takedown(&vm->mm);
+		list_del(&vm->global_link);
+	}
 	intel_gmch_remove();
 	intel_gmch_remove();
 }
 }
 
 

+ 14 - 10
drivers/tty/vt/vt.c

@@ -3155,8 +3155,7 @@ int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 		con_back = &registered_con_driver[i];
 		con_back = &registered_con_driver[i];
 
 
-		if (con_back->con &&
-		    !(con_back->flag & CON_DRIVER_FLAG_MODULE)) {
+		if (con_back->con && con_back->con != csw) {
 			defcsw = con_back->con;
 			defcsw = con_back->con;
 			retval = 0;
 			retval = 0;
 			break;
 			break;
@@ -3261,6 +3260,7 @@ static int vt_unbind(struct con_driver *con)
 {
 {
 	const struct consw *csw = NULL;
 	const struct consw *csw = NULL;
 	int i, more = 1, first = -1, last = -1, deflt = 0;
 	int i, more = 1, first = -1, last = -1, deflt = 0;
+	int ret;
 
 
  	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
  	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
 	    con_is_graphics(con->con, con->first, con->last))
 	    con_is_graphics(con->con, con->first, con->last))
@@ -3286,8 +3286,10 @@ static int vt_unbind(struct con_driver *con)
 
 
 		if (first != -1) {
 		if (first != -1) {
 			console_lock();
 			console_lock();
-			do_unbind_con_driver(csw, first, last, deflt);
+			ret = do_unbind_con_driver(csw, first, last, deflt);
 			console_unlock();
 			console_unlock();
+			if (ret != 0)
+				return ret;
 		}
 		}
 
 
 		first = -1;
 		first = -1;
@@ -3574,17 +3576,20 @@ err:
  */
  */
 int do_unregister_con_driver(const struct consw *csw)
 int do_unregister_con_driver(const struct consw *csw)
 {
 {
-	int i, retval = -ENODEV;
+	int i;
 
 
 	/* cannot unregister a bound driver */
 	/* cannot unregister a bound driver */
 	if (con_is_bound(csw))
 	if (con_is_bound(csw))
-		goto err;
+		return -EBUSY;
+
+	if (csw == conswitchp)
+		return -EINVAL;
 
 
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
 		struct con_driver *con_driver = &registered_con_driver[i];
 		struct con_driver *con_driver = &registered_con_driver[i];
 
 
 		if (con_driver->con == csw &&
 		if (con_driver->con == csw &&
-		    con_driver->flag & CON_DRIVER_FLAG_MODULE) {
+		    con_driver->flag & CON_DRIVER_FLAG_INIT) {
 			vtconsole_deinit_device(con_driver);
 			vtconsole_deinit_device(con_driver);
 			device_destroy(vtconsole_class,
 			device_destroy(vtconsole_class,
 				       MKDEV(0, con_driver->node));
 				       MKDEV(0, con_driver->node));
@@ -3595,12 +3600,11 @@ int do_unregister_con_driver(const struct consw *csw)
 			con_driver->flag = 0;
 			con_driver->flag = 0;
 			con_driver->first = 0;
 			con_driver->first = 0;
 			con_driver->last = 0;
 			con_driver->last = 0;
-			retval = 0;
-			break;
+			return 0;
 		}
 		}
 	}
 	}
-err:
-	return retval;
+
+	return -ENODEV;
 }
 }
 EXPORT_SYMBOL_GPL(do_unregister_con_driver);
 EXPORT_SYMBOL_GPL(do_unregister_con_driver);
 
 

+ 1 - 0
drivers/video/console/dummycon.c

@@ -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);

+ 1 - 0
drivers/video/console/vgacon.c

@@ -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");