diff options
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_stub.c | 11 | ||||
-rw-r--r-- | include/drm/drmP.h | 9 |
3 files changed, 34 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 8ac7fbf6b2b7..08d14df3bb42 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -300,6 +300,18 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
300 | goto out_free; | 300 | goto out_free; |
301 | } | 301 | } |
302 | } | 302 | } |
303 | mutex_lock(&dev->struct_mutex); | ||
304 | if (dev->driver->master_set) { | ||
305 | ret = dev->driver->master_set(dev, priv, true); | ||
306 | if (ret) { | ||
307 | /* drop both references if this fails */ | ||
308 | drm_master_put(&priv->minor->master); | ||
309 | drm_master_put(&priv->master); | ||
310 | mutex_unlock(&dev->struct_mutex); | ||
311 | goto out_free; | ||
312 | } | ||
313 | } | ||
314 | mutex_unlock(&dev->struct_mutex); | ||
303 | } else { | 315 | } else { |
304 | /* get a reference to the master */ | 316 | /* get a reference to the master */ |
305 | priv->master = drm_master_get(priv->minor->master); | 317 | priv->master = drm_master_get(priv->minor->master); |
@@ -533,6 +545,8 @@ int drm_release(struct inode *inode, struct file *filp) | |||
533 | 545 | ||
534 | if (file_priv->minor->master == file_priv->master) { | 546 | if (file_priv->minor->master == file_priv->master) { |
535 | /* drop the reference held my the minor */ | 547 | /* drop the reference held my the minor */ |
548 | if (dev->driver->master_drop) | ||
549 | dev->driver->master_drop(dev, file_priv, true); | ||
536 | drm_master_put(&file_priv->minor->master); | 550 | drm_master_put(&file_priv->minor->master); |
537 | } | 551 | } |
538 | } | 552 | } |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index adb864dfef3e..2c1b52847e9e 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
@@ -174,6 +174,8 @@ void drm_master_put(struct drm_master **master) | |||
174 | int drm_setmaster_ioctl(struct drm_device *dev, void *data, | 174 | int drm_setmaster_ioctl(struct drm_device *dev, void *data, |
175 | struct drm_file *file_priv) | 175 | struct drm_file *file_priv) |
176 | { | 176 | { |
177 | int ret = 0; | ||
178 | |||
177 | if (file_priv->is_master) | 179 | if (file_priv->is_master) |
178 | return 0; | 180 | return 0; |
179 | 181 | ||
@@ -188,6 +190,13 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, | |||
188 | mutex_lock(&dev->struct_mutex); | 190 | mutex_lock(&dev->struct_mutex); |
189 | file_priv->minor->master = drm_master_get(file_priv->master); | 191 | file_priv->minor->master = drm_master_get(file_priv->master); |
190 | file_priv->is_master = 1; | 192 | file_priv->is_master = 1; |
193 | if (dev->driver->master_set) { | ||
194 | ret = dev->driver->master_set(dev, file_priv, false); | ||
195 | if (unlikely(ret != 0)) { | ||
196 | file_priv->is_master = 0; | ||
197 | drm_master_put(&file_priv->minor->master); | ||
198 | } | ||
199 | } | ||
191 | mutex_unlock(&dev->struct_mutex); | 200 | mutex_unlock(&dev->struct_mutex); |
192 | } | 201 | } |
193 | 202 | ||
@@ -204,6 +213,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, | |||
204 | return -EINVAL; | 213 | return -EINVAL; |
205 | 214 | ||
206 | mutex_lock(&dev->struct_mutex); | 215 | mutex_lock(&dev->struct_mutex); |
216 | if (dev->driver->master_drop) | ||
217 | dev->driver->master_drop(dev, file_priv, false); | ||
207 | drm_master_put(&file_priv->minor->master); | 218 | drm_master_put(&file_priv->minor->master); |
208 | file_priv->is_master = 0; | 219 | file_priv->is_master = 0; |
209 | mutex_unlock(&dev->struct_mutex); | 220 | mutex_unlock(&dev->struct_mutex); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1b72a526ba64..770772c014aa 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -774,6 +774,15 @@ struct drm_driver { | |||
774 | /* Master routines */ | 774 | /* Master routines */ |
775 | int (*master_create)(struct drm_device *dev, struct drm_master *master); | 775 | int (*master_create)(struct drm_device *dev, struct drm_master *master); |
776 | void (*master_destroy)(struct drm_device *dev, struct drm_master *master); | 776 | void (*master_destroy)(struct drm_device *dev, struct drm_master *master); |
777 | /** | ||
778 | * master_set is called whenever the minor master is set. | ||
779 | * master_drop is called whenever the minor master is dropped. | ||
780 | */ | ||
781 | |||
782 | int (*master_set)(struct drm_device *dev, struct drm_file *file_priv, | ||
783 | bool from_open); | ||
784 | void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv, | ||
785 | bool from_release); | ||
777 | 786 | ||
778 | int (*proc_init)(struct drm_minor *minor); | 787 | int (*proc_init)(struct drm_minor *minor); |
779 | void (*proc_cleanup)(struct drm_minor *minor); | 788 | void (*proc_cleanup)(struct drm_minor *minor); |