aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2009-12-02 13:15:25 -0500
committerDave Airlie <airlied@redhat.com>2009-12-03 17:55:46 -0500
commit862302ffe422378a5213f558fc5cdf62c37050a9 (patch)
tree13557874eb479023e5a64f12990416045ea60818
parent9340d8cfeacd16cef1cbe94527f7baaed7640669 (diff)
drm: Add support for drm master_[set|drop] callbacks.
The vmwgfx driver has a per master rw lock around TTM, to guarantee mutual exclusion when needed. This is typically when all evictable buffers are evicted due to 1) vt switch 2) master switch 3) suspend / resume. In the multi-master case, on master switch the new master takes the previously active master lock in write mode, and then evicts all buffers. Any clients to previous masters will then block on that lock when trying to validate a buffer. fbdev also acts as a virtual master wrt this. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Jakob Bornecrantz <jakob@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_fops.c14
-rw-r--r--drivers/gpu/drm/drm_stub.c11
-rw-r--r--include/drm/drmP.h9
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)
174int drm_setmaster_ioctl(struct drm_device *dev, void *data, 174int 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);