From: Stuart Abercrombie <sabercrom...@chromium.org>

In several places, including the interrupt handler, the i915 driver assumes
it can deref. dev->primary->master->driver_priv if dev->primary->master
is non-NULL.  This wasn't true if drm_open_helper was midway through, so
rearrange the initialization order.

v2: Address this in drm_open_helper instead of the various access points --
basically Stephane's fix.

Signed-off-by: Stuart Abercrombie <sabercrombie at chromium.org>
Signed-off-by: St?phane Marchesin <marcheu at chromium.org>
---
 drivers/gpu/drm/drm_fops.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7f2af9a..3df3032 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -260,9 +260,11 @@ static int drm_open_helper(struct inode *inode, struct 
file *filp,
         * any master object for render clients */
        mutex_lock(&dev->struct_mutex);
        if (!priv->minor->master && !drm_is_render_client(priv)) {
-               /* create a new master */
-               priv->minor->master = drm_master_create(priv->minor);
-               if (!priv->minor->master) {
+               /* create a new master but don't assign it yet
+                * to ensure master->driver_priv is set up first
+                */
+               struct drm_master *master_ptr = drm_master_create(priv->minor);
+               if (!master_ptr) {
                        mutex_unlock(&dev->struct_mutex);
                        ret = -ENOMEM;
                        goto out_close;
@@ -270,7 +272,7 @@ static int drm_open_helper(struct inode *inode, struct file 
*filp,

                priv->is_master = 1;
                /* take another reference for the copy in the local file priv */
-               priv->master = drm_master_get(priv->minor->master);
+               priv->master = drm_master_get(master_ptr);

                priv->authenticated = 1;

@@ -280,7 +282,7 @@ static int drm_open_helper(struct inode *inode, struct file 
*filp,
                        if (ret) {
                                mutex_lock(&dev->struct_mutex);
                                /* drop both references if this fails */
-                               drm_master_put(&priv->minor->master);
+                               drm_master_put(&master_ptr);
                                drm_master_put(&priv->master);
                                mutex_unlock(&dev->struct_mutex);
                                goto out_close;
@@ -291,12 +293,13 @@ static int drm_open_helper(struct inode *inode, struct 
file *filp,
                        ret = dev->driver->master_set(dev, priv, true);
                        if (ret) {
                                /* drop both references if this fails */
-                               drm_master_put(&priv->minor->master);
+                               drm_master_put(&master_ptr);
                                drm_master_put(&priv->master);
                                mutex_unlock(&dev->struct_mutex);
                                goto out_close;
                        }
                }
+               priv->minor->master = master_ptr;
        } else if (!drm_is_render_client(priv)) {
                /* get a reference to the master */
                priv->master = drm_master_get(priv->minor->master);
-- 
1.9.0.rc1.175.g0b1dcb5

Reply via email to