aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2015-11-18 07:43:20 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-11-19 11:00:24 -0500
commit54632abe8ca3db8621673b186c7cc0e869c0032f (patch)
treeb48e3fe26a194df46e96d51272b3de98363039d0
parentce7f172856396d92e82cb0eae420f4ce41c92851 (diff)
drm/i915: Fix oops caused by fbdev initialization failure
intelfb_create() is called once on driver initialization. If it fails, ifbdev->helper.fbdev, ifbdev->fb or ifbdev->fb->obj may be NULL. Further up in the call stack, intel_fbdev_initial_config() calls intel_fbdev_fini() to tear down the ifbdev on failure. This calls intel_fbdev_destroy() which dereferences ifbdev->fb. Fix the ensuing oops. Also check in these functions if ifbdev is not NULL to avoid oops: i915_gem_framebuffer_info() is called on access to debugfs file "i915_gem_framebuffer" and dereferences ifbdev, ifbdev->helper.fb and ifbdev->helper.fb->obj. intel_connector_add_to_fbdev() / intel_connector_remove_from_fbdev() are called when registering / unregistering an mst connector and dereference ifbdev. v3: Drop additional null pointer checks in intel_fbdev_set_suspend(), intel_fbdev_output_poll_changed() and intel_fbdev_restore_mode() since they already check if ifbdev is not NULL, which is sufficient now that intel_fbdev_fini() is called on initialization failure. (Requested by Daniel Vetter <daniel.vetter@ffwll.ch>) Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: http://patchwork.freedesktop.org/patch/msgid/d05f0edf121264a9d0adb8ca713fd8cc4ae068bf.1447938059.git.lukas@wunner.de Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c24
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c10
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c6
3 files changed, 25 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a9af884dadd5..08eb40292933 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1878,17 +1878,19 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
1878 struct drm_i915_private *dev_priv = dev->dev_private; 1878 struct drm_i915_private *dev_priv = dev->dev_private;
1879 1879
1880 ifbdev = dev_priv->fbdev; 1880 ifbdev = dev_priv->fbdev;
1881 fb = to_intel_framebuffer(ifbdev->helper.fb); 1881 if (ifbdev) {
1882 1882 fb = to_intel_framebuffer(ifbdev->helper.fb);
1883 seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", 1883
1884 fb->base.width, 1884 seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
1885 fb->base.height, 1885 fb->base.width,
1886 fb->base.depth, 1886 fb->base.height,
1887 fb->base.bits_per_pixel, 1887 fb->base.depth,
1888 fb->base.modifier[0], 1888 fb->base.bits_per_pixel,
1889 atomic_read(&fb->base.refcount.refcount)); 1889 fb->base.modifier[0],
1890 describe_obj(m, fb->obj); 1890 atomic_read(&fb->base.refcount.refcount));
1891 seq_putc(m, '\n'); 1891 describe_obj(m, fb->obj);
1892 seq_putc(m, '\n');
1893 }
1892#endif 1894#endif
1893 1895
1894 mutex_lock(&dev->mode_config.fb_lock); 1896 mutex_lock(&dev->mode_config.fb_lock);
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 8a604ac797aa..a12d1c7ee0e7 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -408,7 +408,10 @@ static void intel_connector_add_to_fbdev(struct intel_connector *connector)
408{ 408{
409#ifdef CONFIG_DRM_FBDEV_EMULATION 409#ifdef CONFIG_DRM_FBDEV_EMULATION
410 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 410 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
411 drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base); 411
412 if (dev_priv->fbdev)
413 drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper,
414 &connector->base);
412#endif 415#endif
413} 416}
414 417
@@ -416,7 +419,10 @@ static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
416{ 419{
417#ifdef CONFIG_DRM_FBDEV_EMULATION 420#ifdef CONFIG_DRM_FBDEV_EMULATION
418 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 421 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
419 drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base); 422
423 if (dev_priv->fbdev)
424 drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper,
425 &connector->base);
420#endif 426#endif
421} 427}
422 428
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 98772d37b09f..cdbef32897f0 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -529,8 +529,10 @@ static void intel_fbdev_destroy(struct drm_device *dev,
529 529
530 drm_fb_helper_fini(&ifbdev->helper); 530 drm_fb_helper_fini(&ifbdev->helper);
531 531
532 drm_framebuffer_unregister_private(&ifbdev->fb->base); 532 if (ifbdev->fb) {
533 drm_framebuffer_remove(&ifbdev->fb->base); 533 drm_framebuffer_unregister_private(&ifbdev->fb->base);
534 drm_framebuffer_remove(&ifbdev->fb->base);
535 }
534} 536}
535 537
536/* 538/*