All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukas Wunner <lukas@wunner.de>
To: intel-gfx@lists.freedesktop.org
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Subject: [PATCH v2 1/2] drm/i915: Fix oops caused by fbdev initialization failure
Date: Thu, 5 Nov 2015 10:42:40 +0100	[thread overview]
Message-ID: <f07beea8143322d54dfeb929b91e0361ced273d5.1446987413.git.lukas@wunner.de> (raw)
In-Reply-To: <cover.1446987413.git.lukas@wunner.de>

intelfb_create() is called once on driver initialization. If it fails,
ifbdev->helper.fbdev, ifbdev->fb or ifbdev->fb->obj may be NULL.

intel_fbdev_destroy() is called on driver unload and dereferences
ifbdev->fb.

intel_fbdev_set_suspend() is called on suspend/resume and dereferences
ifbdev->helper.fbdev and ifbdev->fb->obj.

intel_fbdev_output_poll_changed() is called on hotplug events and calls
drm_fb_helper_hotplug_event(). If ifbdev->helper.fb is NULL it will
signal a delayed_hotplug ad infinitum; if it is not NULL it will call
drm_fb_helper_set_par() which dereferences ifbdev->helper.fbdev.

intel_fbdev_restore_mode() is called on lastclose and dereferences
ifbdev->fb->obj. It also calls __drm_atomic_helper_set_config() which
WARNs if ifbdev->fb is NULL, and drm_fb_helper_set_par() which
dereferences ifbdev->helper.fbdev.

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.

Basically if fbdev creation fails, we end up with an ifbdev that's
only partially initialized and the driver will oops on unload,
the next suspend/resume cycle, hotplug events, when X11 is stopped
or when accessing debugfs file "i915_gem_framebuffer".

After the fbdev was destroyed with intel_fbdev_fini(), the driver
will oops on mst hotplug events.

Fix it.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 24 +++++++++++++-----------
 drivers/gpu/drm/i915/intel_dp_mst.c | 10 ++++++++--
 drivers/gpu/drm/i915/intel_fbdev.c  | 16 ++++++++++------
 3 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 5659d4c..17821cf 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1877,17 +1877,19 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	ifbdev = dev_priv->fbdev;
-	fb = to_intel_framebuffer(ifbdev->helper.fb);
-
-	seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
-		   fb->base.width,
-		   fb->base.height,
-		   fb->base.depth,
-		   fb->base.bits_per_pixel,
-		   fb->base.modifier[0],
-		   atomic_read(&fb->base.refcount.refcount));
-	describe_obj(m, fb->obj);
-	seq_putc(m, '\n');
+	if (ifbdev && ifbdev->helper.fb && ifbdev->fb->obj) {
+		fb = to_intel_framebuffer(ifbdev->helper.fb);
+
+		seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
+			   fb->base.width,
+			   fb->base.height,
+			   fb->base.depth,
+			   fb->base.bits_per_pixel,
+			   fb->base.modifier[0],
+			   atomic_read(&fb->base.refcount.refcount));
+		describe_obj(m, fb->obj);
+		seq_putc(m, '\n');
+	}
 #endif
 
 	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 0639275..735368e 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -414,7 +414,10 @@ static void intel_connector_add_to_fbdev(struct intel_connector *connector)
 {
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-	drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base);
+
+	if (dev_priv->fbdev)
+		drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper,
+						&connector->base);
 #endif
 }
 
@@ -422,7 +425,10 @@ static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
 {
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-	drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base);
+
+	if (dev_priv->fbdev)
+		drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper,
+						   &connector->base);
 #endif
 }
 
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index db82ad4..05484ba 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,
 
 	drm_fb_helper_fini(&ifbdev->helper);
 
-	drm_framebuffer_unregister_private(&ifbdev->fb->base);
-	drm_framebuffer_remove(&ifbdev->fb->base);
+	if (ifbdev->fb) {
+		drm_framebuffer_unregister_private(&ifbdev->fb->base);
+		drm_framebuffer_remove(&ifbdev->fb->base);
+	}
 }
 
 /*
@@ -734,7 +736,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
 	struct intel_fbdev *ifbdev = dev_priv->fbdev;
 	struct fb_info *info;
 
-	if (!ifbdev)
+	if (!ifbdev || !ifbdev->fb || !ifbdev->fb->obj || !ifbdev->helper.fbdev)
 		return;
 
 	info = ifbdev->helper.fbdev;
@@ -780,8 +782,10 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	if (dev_priv->fbdev)
-		drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
+	struct intel_fbdev *ifbdev = dev_priv->fbdev;
+
+	if (ifbdev && ifbdev->fb && ifbdev->fb->obj && ifbdev->helper.fbdev)
+		drm_fb_helper_hotplug_event(&ifbdev->helper);
 }
 
 void intel_fbdev_restore_mode(struct drm_device *dev)
@@ -791,7 +795,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
 	struct intel_fbdev *ifbdev = dev_priv->fbdev;
 	struct drm_fb_helper *fb_helper;
 
-	if (!ifbdev)
+	if (!ifbdev || !ifbdev->fb || !ifbdev->fb->obj || !ifbdev->helper.fbdev)
 		return;
 
 	fb_helper = &ifbdev->helper;
-- 
1.8.5.2 (Apple Git-48)

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2015-11-08 16:18 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-30  9:06 [PATCH v5 1/2] drm/i915: Fix failure paths around initial fbdev allocation Lukas Wunner
2015-07-04  9:50 ` [PATCH v5 2/2] drm/i915: On fb alloc failure, unref gem object where it gets refed Lukas Wunner
2015-10-13 15:39   ` Ville Syrjälä
2015-10-13 15:04 ` [PATCH v5 1/2] drm/i915: Fix failure paths around initial fbdev allocation Ville Syrjälä
2015-10-14  9:35   ` Chris Wilson
2015-10-15 17:14   ` Lukas Wunner
2015-10-15 17:22     ` Daniel Vetter
2015-10-15 17:34     ` Ville Syrjälä
2015-10-18 18:03       ` Lukas Wunner
2015-10-25 11:14       ` [PATCH v6 0/4] fbdev deadlock & failure path fixes Lukas Wunner
2015-06-30  9:06         ` [PATCH v6 3/4] drm/i915: Fix failure paths around initial fbdev allocation Lukas Wunner
2015-10-30 18:28           ` Daniel Vetter
2015-11-07 10:41             ` [PATCH v7 0/3] fbdev fixes (reviewed) Lukas Wunner
2015-06-30  9:06               ` [PATCH v7 3/3] drm/i915: Fix failure paths around initial fbdev allocation Lukas Wunner
2015-07-04  9:50               ` [PATCH v7 1/3] drm/i915: On fb alloc failure, unref gem object where it gets refed Lukas Wunner
2015-10-22 11:37               ` [PATCH v7 2/3] drm/i915: Fix double unref in intelfb_alloc failure path Lukas Wunner
2015-11-09 14:23               ` [PATCH v7 0/3] fbdev fixes (reviewed) Jani Nikula
2015-11-12 19:20                 ` Lukas Wunner
2015-11-13  7:06                   ` Jani Nikula
2015-11-17 13:44                     ` Daniel Vetter
2015-07-04  9:50         ` [PATCH v6 1/4] drm/i915: On fb alloc failure, unref gem object where it gets refed Lukas Wunner
2015-10-22 11:37         ` [PATCH v6 2/4] drm/i915: Fix double unref in intelfb_alloc failure path Lukas Wunner
2015-10-30 18:17           ` Daniel Vetter
2015-10-23 22:27         ` [PATCH v6 4/4] drm/i915: Fix error handling in intelfb_create Lukas Wunner
2015-10-30 18:23           ` Daniel Vetter
2015-11-08 12:56             ` [PATCH v2 0/2] fbdev fixes (need review) Lukas Wunner
2015-11-03  7:00               ` [PATCH v2 2/2] drm/i915: Tear down fbdev if initialization fails Lukas Wunner
2015-11-05  9:42               ` Lukas Wunner [this message]
2015-11-17 13:51               ` [PATCH v2 0/2] fbdev fixes (need review) Daniel Vetter

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=f07beea8143322d54dfeb929b91e0361ced273d5.1446987413.git.lukas@wunner.de \
    --to=lukas@wunner.de \
    --cc=daniel.vetter@ffwll.ch \
    --cc=intel-gfx@lists.freedesktop.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.