From 3dadef6c96c8aa6e67f83b30504256a0605ee4d6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 14:11:36 +0200 Subject: drm: kill dev->context_wait No one ever waits on this waitqueue, so the wake_up call is wasted. Remove it all. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 3a24385e036..0dcbbdb6f97 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -81,7 +81,6 @@ static int drm_setup(struct drm_device * dev) dev->last_context = 0; dev->last_switch = 0; dev->last_checked = 0; - init_waitqueue_head(&dev->context_wait); dev->if_version = 0; dev->ctx_start = 0; -- cgit v1.2.3-70-g09d2 From a17800c70129d5976a52c42f04a16a0f1d9df4b2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 14:11:37 +0200 Subject: drm: remove dev->last_switch Only ever assigned in the context code for real, with no readers anywhere. Remove it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_context.c | 1 - drivers/gpu/drm/drm_fops.c | 1 - include/drm/drmP.h | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index 5cc17f32eb7..224ff965bcf 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -251,7 +251,6 @@ static int drm_context_switch_complete(struct drm_device *dev, struct drm_file *file_priv, int new) { dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ - dev->last_switch = jiffies; if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) { DRM_ERROR("Lock isn't held after context switch\n"); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 0dcbbdb6f97..c14fdc1c109 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -79,7 +79,6 @@ static int drm_setup(struct drm_device * dev) dev->interrupt_flag = 0; dev->dma_flag = 0; dev->last_context = 0; - dev->last_switch = 0; dev->last_checked = 0; dev->if_version = 0; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 44991331310..089e82028e7 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1135,7 +1135,6 @@ struct drm_device { __volatile__ long dma_flag; /**< DMA dispatch flag */ int last_checked; /**< Last context checked for DMA */ int last_context; /**< Last current context */ - unsigned long last_switch; /**< jiffies at last context switch */ /*@} */ struct work_struct work; -- cgit v1.2.3-70-g09d2 From c78d7531031cb6d163e7450bda563c267beef777 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 14:11:38 +0200 Subject: drm: kill dev->interrupt_flag and dev->dma_flag Completely unused, so just remove them. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 2 -- include/drm/drmP.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index c14fdc1c109..386c304c5cb 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -76,8 +76,6 @@ static int drm_setup(struct drm_device * dev) dev->sigdata.lock = NULL; dev->context_flag = 0; - dev->interrupt_flag = 0; - dev->dma_flag = 0; dev->last_context = 0; dev->last_checked = 0; dev->if_version = 0; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 089e82028e7..1ec806f76ad 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1131,8 +1131,6 @@ struct drm_device { /*@{ */ int irq_enabled; /**< True if irq handler is enabled */ __volatile__ long context_flag; /**< Context swapping flag */ - __volatile__ long interrupt_flag; /**< Interruption handler flag */ - __volatile__ long dma_flag; /**< DMA dispatch flag */ int last_checked; /**< Last context checked for DMA */ int last_context; /**< Last current context */ /*@} */ -- cgit v1.2.3-70-g09d2 From c7e00b6d6a08772fac43b0fcea7fb48e6a1fe390 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 14:11:39 +0200 Subject: drm: kill dev->ctx_start and dev->lck_start Again completely unused, so just remove it. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 3 --- include/drm/drmP.h | 2 -- 2 files changed, 5 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 386c304c5cb..a3714a0235c 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -80,9 +80,6 @@ static int drm_setup(struct drm_device * dev) dev->last_checked = 0; dev->if_version = 0; - dev->ctx_start = 0; - dev->lck_start = 0; - dev->buf_async = NULL; init_waitqueue_head(&dev->buf_readers); init_waitqueue_head(&dev->buf_writers); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1ec806f76ad..04036957150 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1170,8 +1170,6 @@ struct drm_device { spinlock_t event_lock; /*@} */ - cycles_t ctx_start; - cycles_t lck_start; struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */ wait_queue_head_t buf_readers; /**< Processes waiting to read */ -- cgit v1.2.3-70-g09d2 From 494f38e4e0c5ffca110e361cd3391f25313b52c7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 14:11:41 +0200 Subject: drm: kill dev->buf_readers and dev->buf_writers Again totally unused, so just remove them. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 2 -- include/drm/drmP.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index a3714a0235c..57e30145f68 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -81,8 +81,6 @@ static int drm_setup(struct drm_device * dev) dev->if_version = 0; dev->buf_async = NULL; - init_waitqueue_head(&dev->buf_readers); - init_waitqueue_head(&dev->buf_writers); DRM_DEBUG("\n"); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04036957150..6cde9246513 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1172,8 +1172,6 @@ struct drm_device { /*@} */ struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */ - wait_queue_head_t buf_readers; /**< Processes waiting to read */ - wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */ struct drm_agp_head *agp; /**< AGP data */ -- cgit v1.2.3-70-g09d2 From 23367ff49065505e4a255dba2117f654ca26063f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 17:51:10 +0200 Subject: drm: rip out dev->last_checked Only ever re-cleared in drm_setup, otherwise completely unused. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 1 - include/drm/drmP.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 57e30145f68..72acae908a7 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -77,7 +77,6 @@ static int drm_setup(struct drm_device * dev) dev->context_flag = 0; dev->last_context = 0; - dev->last_checked = 0; dev->if_version = 0; dev->buf_async = NULL; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1ea404fd745..dd03fd4239a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1131,7 +1131,6 @@ struct drm_device { /*@{ */ int irq_enabled; /**< True if irq handler is enabled */ __volatile__ long context_flag; /**< Context swapping flag */ - int last_checked; /**< Last context checked for DMA */ int last_context; /**< Last current context */ /*@} */ -- cgit v1.2.3-70-g09d2 From e2e99a8206bcce6f2d3d72ff8be42859f98dbcda Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 8 Aug 2013 15:41:19 +0200 Subject: drm: mark dma setup/teardown as legacy systems And hide the checks a bit better. This was already disallowed for modesetting drivers, so no functinal change here. Reviewed-by: Eric Anholt Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dma.c | 17 +++++++++++++++-- drivers/gpu/drm/drm_drv.c | 4 +--- drivers/gpu/drm/drm_fops.c | 12 +++--------- include/drm/drmP.h | 4 ++-- 4 files changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c index 495b5fd2787..8a140a95375 100644 --- a/drivers/gpu/drm/drm_dma.c +++ b/drivers/gpu/drm/drm_dma.c @@ -44,10 +44,18 @@ * * Allocate and initialize a drm_device_dma structure. */ -int drm_dma_setup(struct drm_device *dev) +int drm_legacy_dma_setup(struct drm_device *dev) { int i; + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) || + drm_core_check_feature(dev, DRIVER_MODESET)) { + return 0; + } + + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + dev->dma = kzalloc(sizeof(*dev->dma), GFP_KERNEL); if (!dev->dma) return -ENOMEM; @@ -66,11 +74,16 @@ int drm_dma_setup(struct drm_device *dev) * Free all pages associated with DMA buffers, the buffers and pages lists, and * finally the drm_device::dma structure itself. */ -void drm_dma_takedown(struct drm_device *dev) +void drm_legacy_dma_takedown(struct drm_device *dev) { struct drm_device_dma *dma = dev->dma; int i, j; + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) || + drm_core_check_feature(dev, DRIVER_MODESET)) { + return; + } + if (!dma) return; diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 743b24d7918..5b949a73671 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -205,9 +205,7 @@ int drm_lastclose(struct drm_device * dev) kfree(vma); } - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && - !drm_core_check_feature(dev, DRIVER_MODESET)) - drm_dma_takedown(dev); + drm_legacy_dma_takedown(dev); dev->dev_mapping = NULL; mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 72acae908a7..f343234bd83 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -60,15 +60,9 @@ static int drm_setup(struct drm_device * dev) atomic_set(&dev->ioctl_count, 0); atomic_set(&dev->vma_count, 0); - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && - !drm_core_check_feature(dev, DRIVER_MODESET)) { - dev->buf_use = 0; - atomic_set(&dev->buf_alloc, 0); - - i = drm_dma_setup(dev); - if (i < 0) - return i; - } + i = drm_legacy_dma_setup(dev); + if (i < 0) + return i; for (i = 0; i < ARRAY_SIZE(dev->counts); i++) atomic_set(&dev->counts[i], 0); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 10d9f83a9df..1da25304c28 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1374,8 +1374,8 @@ extern int drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv); /* DMA support (drm_dma.h) */ -extern int drm_dma_setup(struct drm_device *dev); -extern void drm_dma_takedown(struct drm_device *dev); +extern int drm_legacy_dma_setup(struct drm_device *dev); +extern void drm_legacy_dma_takedown(struct drm_device *dev); extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf); extern void drm_core_reclaim_buffers(struct drm_device *dev, struct drm_file *filp); -- cgit v1.2.3-70-g09d2 From 7c510133d93dd6f15ca040733ba7b2891ed61fd1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 8 Aug 2013 15:41:21 +0200 Subject: drm: mark context support as a legacy subsystem So after a lot of digging around in git histories it looks like this has only ever be used by dri1 render clients. Hence we can fully disable the entire thing for modesetting drivers and so greatly reduce the attack surface for potential exploits (or at least tools like trinity ...). Also add the drm_legacy prefix for functions which are called from common code. To further reduce the impact on common code also extract all the ctx release handling into a function (instead of only releasing individual handles) and make ctxbitmap_cleanup return void - it can never fail. Reviewed-by: Eric Anholt Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_context.c | 73 ++++++++++++++++++++++++++++++++++++++----- drivers/gpu/drm/drm_fops.c | 21 +------------ drivers/gpu/drm/drm_stub.c | 10 ++---- include/drm/drmP.h | 7 +++-- 4 files changed, 72 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index 224ff965bcf..b4fb86d8985 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -42,10 +42,6 @@ #include -/******************************************************************/ -/** \name Context bitmap support */ -/*@{*/ - /** * Free a handle from the context bitmap. * @@ -56,13 +52,48 @@ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex * lock. */ -void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) +static void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) { + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + mutex_lock(&dev->struct_mutex); idr_remove(&dev->ctx_idr, ctx_handle); mutex_unlock(&dev->struct_mutex); } +/******************************************************************/ +/** \name Context bitmap support */ +/*@{*/ + +void drm_legacy_ctxbitmap_release(struct drm_device *dev, + struct drm_file *file_priv) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + mutex_lock(&dev->ctxlist_mutex); + if (!list_empty(&dev->ctxlist)) { + struct drm_ctx_list *pos, *n; + + list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { + if (pos->tag == file_priv && + pos->handle != DRM_KERNEL_CONTEXT) { + if (dev->driver->context_dtor) + dev->driver->context_dtor(dev, + pos->handle); + + drm_ctxbitmap_free(dev, pos->handle); + + list_del(&pos->head); + kfree(pos); + --dev->ctx_count; + } + } + } + mutex_unlock(&dev->ctxlist_mutex); +} + /** * Context bitmap allocation. * @@ -90,10 +121,12 @@ static int drm_ctxbitmap_next(struct drm_device * dev) * * Initialise the drm_device::ctx_idr */ -int drm_ctxbitmap_init(struct drm_device * dev) +void drm_legacy_ctxbitmap_init(struct drm_device * dev) { + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + idr_init(&dev->ctx_idr); - return 0; } /** @@ -104,7 +137,7 @@ int drm_ctxbitmap_init(struct drm_device * dev) * Free all idr members using drm_ctx_sarea_free helper function * while holding the drm_device::struct_mutex lock. */ -void drm_ctxbitmap_cleanup(struct drm_device * dev) +void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev) { mutex_lock(&dev->struct_mutex); idr_destroy(&dev->ctx_idr); @@ -136,6 +169,9 @@ int drm_getsareactx(struct drm_device *dev, void *data, struct drm_local_map *map; struct drm_map_list *_entry; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + mutex_lock(&dev->struct_mutex); map = idr_find(&dev->ctx_idr, request->ctx_id); @@ -180,6 +216,9 @@ int drm_setsareactx(struct drm_device *dev, void *data, struct drm_local_map *map = NULL; struct drm_map_list *r_list = NULL; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + mutex_lock(&dev->struct_mutex); list_for_each_entry(r_list, &dev->maplist, head) { if (r_list->map @@ -280,6 +319,9 @@ int drm_resctx(struct drm_device *dev, void *data, struct drm_ctx ctx; int i; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + if (res->count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { @@ -310,6 +352,9 @@ int drm_addctx(struct drm_device *dev, void *data, struct drm_ctx_list *ctx_entry; struct drm_ctx *ctx = data; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + ctx->handle = drm_ctxbitmap_next(dev); if (ctx->handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ @@ -353,6 +398,9 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx *ctx = data; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + /* This is 0, because we don't handle any context flags */ ctx->flags = 0; @@ -375,6 +423,9 @@ int drm_switchctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + DRM_DEBUG("%d\n", ctx->handle); return drm_context_switch(dev, dev->last_context, ctx->handle); } @@ -395,6 +446,9 @@ int drm_newctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + DRM_DEBUG("%d\n", ctx->handle); drm_context_switch_complete(dev, file_priv, ctx->handle); @@ -417,6 +471,9 @@ int drm_rmctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + DRM_DEBUG("%d\n", ctx->handle); if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index f343234bd83..10334999f22 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -474,26 +474,7 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); - mutex_lock(&dev->ctxlist_mutex); - if (!list_empty(&dev->ctxlist)) { - struct drm_ctx_list *pos, *n; - - list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { - if (pos->tag == file_priv && - pos->handle != DRM_KERNEL_CONTEXT) { - if (dev->driver->context_dtor) - dev->driver->context_dtor(dev, - pos->handle); - - drm_ctxbitmap_free(dev, pos->handle); - - list_del(&pos->head); - kfree(pos); - --dev->ctx_count; - } - } - } - mutex_unlock(&dev->ctxlist_mutex); + drm_legacy_ctxbitmap_release(dev, file_priv); mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index d663f7d66da..aa0664d9106 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -288,13 +288,7 @@ int drm_fill_in_dev(struct drm_device *dev, goto error_out_unreg; } - - - retcode = drm_ctxbitmap_init(dev); - if (retcode) { - DRM_ERROR("Cannot allocate memory for context bitmap.\n"); - goto error_out_unreg; - } + drm_legacy_ctxbitmap_init(dev); if (driver->driver_features & DRIVER_GEM) { retcode = drm_gem_init(dev); @@ -463,7 +457,7 @@ void drm_put_dev(struct drm_device *dev) drm_rmmap(dev, r_list->map); drm_ht_remove(&dev->map_hash); - drm_ctxbitmap_cleanup(dev); + drm_legacy_ctxbitmap_cleanup(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_put_minor(&dev->control); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1da25304c28..277f307e053 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1313,9 +1313,10 @@ extern int drm_newctx(struct drm_device *dev, void *data, extern int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_ctxbitmap_init(struct drm_device *dev); -extern void drm_ctxbitmap_cleanup(struct drm_device *dev); -extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle); +extern void drm_legacy_ctxbitmap_init(struct drm_device *dev); +extern void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev); +extern void drm_legacy_ctxbitmap_release(struct drm_device *dev, + struct drm_file *file_priv); extern int drm_setsareactx(struct drm_device *dev, void *data, struct drm_file *file_priv); -- cgit v1.2.3-70-g09d2 From b0e898ac555e96e7863a5ee95d70f3625f1db5e2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 8 Aug 2013 15:41:23 +0200 Subject: drm: remove FASYNC support So I've stumbled over drm_fasync and wondered what it does. Digging that up is quite a story. First I've had to read up on what this does and ended up being rather bewildered why peopled loved signals so much back in the days that they've created SIGIO just for that ... Then I wondered how this ever works, and what that strange "No-op." comment right above it should mean. After all calling the core fasync helper is pretty obviously not a noop. After reading through the kernels FASYNC implementation I've noticed that signals are only sent out to the processes attached with FASYNC by calling kill_fasync. No merged drm driver has ever done that. After more digging I've found out that the only driver that ever used this is the so called GAMMA driver. I've frankly never heard of such a gpu brand ever before. Now FASYNC seems to not have been the only bad thing with that driver, since Dave Airlie removed it from the drm driver with prejudice: commit 1430163b4bbf7b00367ea1066c1c5fe85dbeefed Author: Dave Airlie Date: Sun Aug 29 12:04:35 2004 +0000 Drop GAMMA DRM from a great height ... Long story short, the drm fasync support seems to be doing absolutely nothing. And the only user of it was never merged into the upstream kernel. And we don't need any fops->fasync callback since the fcntl implementation in the kernel already implements the noop case correctly. So stop this particular cargo-cult and rip it all out. v2: Kill drm_fasync assignments in rcar (newly added) and imx drivers (somehow I've missed that one in staging). Also drop the reference in the drm DocBook. ARM compile-fail reported by Rob Clark. v3: Move the removal of dev->buf_asnyc assignment in drm_setup to this patch here. v4: Actually git add ... tsk. Cc: Dave Airlie Cc: Laurent Pinchart Cc: Rob Clark Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter Reviewed-by: David Herrmann Signed-off-by: Dave Airlie --- Documentation/DocBook/drm.tmpl | 1 - drivers/gpu/drm/ast/ast_drv.c | 1 - drivers/gpu/drm/cirrus/cirrus_drv.c | 1 - drivers/gpu/drm/drm_fops.c | 14 -------------- drivers/gpu/drm/gma500/psb_drv.c | 1 - drivers/gpu/drm/i810/i810_dma.c | 1 - drivers/gpu/drm/i810/i810_drv.c | 1 - drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/mga/mga_drv.c | 1 - drivers/gpu/drm/mgag200/mgag200_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_drm.c | 1 - drivers/gpu/drm/omapdrm/omap_drv.c | 1 - drivers/gpu/drm/qxl/qxl_drv.c | 1 - drivers/gpu/drm/r128/r128_drv.c | 1 - drivers/gpu/drm/radeon/radeon_drv.c | 2 -- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 - drivers/gpu/drm/savage/savage_drv.c | 1 - drivers/gpu/drm/shmobile/shmob_drm_drv.c | 1 - drivers/gpu/drm/sis/sis_drv.c | 1 - drivers/gpu/drm/tdfx/tdfx_drv.c | 1 - drivers/gpu/drm/tilcdc/tilcdc_drv.c | 1 - drivers/gpu/drm/udl/udl_drv.c | 1 - drivers/gpu/drm/via/via_drv.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 - drivers/gpu/host1x/drm/drm.c | 1 - drivers/staging/imx-drm/imx-drm-core.c | 1 - include/drm/drmP.h | 3 --- 27 files changed, 43 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 87e22ecd928..9494ab8af9e 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2504,7 +2504,6 @@ void (*postclose) (struct drm_device *, struct drm_file *); .poll = drm_poll, .read = drm_read, - .fasync = drm_fasync, .llseek = no_llseek, diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index a144fb04485..60f1ce3998c 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -190,7 +190,6 @@ static const struct file_operations ast_fops = { .unlocked_ioctl = drm_ioctl, .mmap = ast_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index d35d99c15f8..dd9c908ab3f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -85,7 +85,6 @@ static const struct file_operations cirrus_driver_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif - .fasync = drm_fasync, }; static struct drm_driver driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_USE_MTRR, diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 10334999f22..1817f03efe8 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -73,8 +73,6 @@ static int drm_setup(struct drm_device * dev) dev->last_context = 0; dev->if_version = 0; - dev->buf_async = NULL; - DRM_DEBUG("\n"); /* @@ -372,18 +370,6 @@ out_put_pid: return ret; } -/** No-op. */ -int drm_fasync(int fd, struct file *filp, int on) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->minor->dev; - - DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, - (long)old_encode_dev(priv->minor->device)); - return fasync_helper(fd, filp, on, &dev->buf_async); -} -EXPORT_SYMBOL(drm_fasync); - static void drm_master_release(struct drm_device *dev, struct file *filp) { struct drm_file *file_priv = filp->private_data; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index d13c2fc848b..99b5293972c 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -622,7 +622,6 @@ static const struct file_operations psb_gem_fops = { .unlocked_ioctl = psb_unlocked_ioctl, .mmap = drm_gem_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, }; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index eac755bb8f9..ab1892eb107 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -113,7 +113,6 @@ static const struct file_operations i810_buffer_fops = { .release = drm_release, .unlocked_ioctl = drm_ioctl, .mmap = i810_mmap_buffers, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 2e91fc3580b..d85c05b4877 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -49,7 +49,6 @@ static const struct file_operations i810_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 13457e3e9ca..9411a745ada 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -994,7 +994,6 @@ static const struct file_operations i915_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_gem_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, #ifdef CONFIG_COMPAT .compat_ioctl = i915_compat_ioctl, diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 17d0a637e4f..fe71e1e44e4 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -50,7 +50,6 @@ static const struct file_operations mga_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = mga_compat_ioctl, #endif diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index bd919647873..b570127ae3b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -81,7 +81,6 @@ static const struct file_operations mgag200_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = mgag200_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 1faa75f4239..b29d04b822a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -673,7 +673,6 @@ nouveau_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = nouveau_ttm_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, #if defined(CONFIG_COMPAT) .compat_ioctl = nouveau_compat_ioctl, diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 47e64f91625..2603d909f49 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -592,7 +592,6 @@ static const struct file_operations omapdriver_fops = { .release = drm_release, .mmap = omap_gem_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, .llseek = noop_llseek, }; diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 48f2dfdeabc..514118ae72d 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -84,7 +84,6 @@ static const struct file_operations qxl_fops = { .release = drm_release, .unlocked_ioctl = drm_ioctl, .poll = drm_poll, - .fasync = drm_fasync, .mmap = qxl_mmap, }; diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 472c38fe123..c2338cbc56a 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -48,7 +48,6 @@ static const struct file_operations r128_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = r128_compat_ioctl, #endif diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 3585f22c5c1..3e52331124d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -266,7 +266,6 @@ static const struct file_operations radeon_driver_old_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, #ifdef CONFIG_COMPAT .compat_ioctl = radeon_compat_ioctl, @@ -375,7 +374,6 @@ static const struct file_operations radeon_driver_kms_fops = { .unlocked_ioctl = drm_ioctl, .mmap = radeon_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, #ifdef CONFIG_COMPAT .compat_ioctl = radeon_kms_compat_ioctl, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0a9f1bb8833..0023f9719cf 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -148,7 +148,6 @@ static const struct file_operations rcar_du_fops = { #endif .poll = drm_poll, .read = drm_read, - .fasync = drm_fasync, .llseek = no_llseek, .mmap = drm_gem_cma_mmap, }; diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 71b2081e783..9135c8bd6fb 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -42,7 +42,6 @@ static const struct file_operations savage_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 7f2ea1a5a45..015551866b4 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -257,7 +257,6 @@ static const struct file_operations shmob_drm_fops = { #endif .poll = drm_poll, .read = drm_read, - .fasync = drm_fasync, .llseek = no_llseek, .mmap = drm_gem_cma_mmap, }; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 5a5325e6b75..b88b2d30210 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -72,7 +72,6 @@ static const struct file_operations sis_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index ddfa743459d..951ec13e4e5 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -48,7 +48,6 @@ static const struct file_operations tdfx_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 14801c2235a..116da199b94 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -497,7 +497,6 @@ static const struct file_operations fops = { #endif .poll = drm_poll, .read = drm_read, - .fasync = drm_fasync, .llseek = no_llseek, .mmap = drm_gem_cma_mmap, }; diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index bb0af58c769..7650dc0d78c 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -65,7 +65,6 @@ static const struct file_operations udl_driver_fops = { .read = drm_read, .unlocked_ioctl = drm_ioctl, .release = drm_release, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index f4ae2032794..448799968a0 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -64,7 +64,6 @@ static const struct file_operations via_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 81ef6bac873..2dd1919485e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1120,7 +1120,6 @@ static const struct file_operations vmwgfx_driver_fops = { .mmap = vmw_mmap, .poll = vmw_fops_poll, .read = vmw_fops_read, - .fasync = drm_fasync, #if defined(CONFIG_COMPAT) .compat_ioctl = drm_compat_ioctl, #endif diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c index b128b90a94f..15684bf073f 100644 --- a/drivers/gpu/host1x/drm/drm.c +++ b/drivers/gpu/host1x/drm/drm.c @@ -508,7 +508,6 @@ static const struct file_operations tegra_drm_fops = { .unlocked_ioctl = drm_ioctl, .mmap = tegra_drm_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index a8900496b98..29607c25b26 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -207,7 +207,6 @@ static const struct file_operations imx_drm_driver_fops = { .unlocked_ioctl = drm_ioctl, .mmap = drm_gem_cma_mmap, .poll = drm_poll, - .fasync = drm_fasync, .read = drm_read, .llseek = noop_llseek, }; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 277f307e053..cef9a507246 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1166,8 +1166,6 @@ struct drm_device { /*@} */ - struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */ - struct drm_agp_head *agp; /**< AGP data */ struct device *dev; /**< Device structure */ @@ -1264,7 +1262,6 @@ extern int drm_lastclose(struct drm_device *dev); extern struct mutex drm_global_mutex; extern int drm_open(struct inode *inode, struct file *filp); extern int drm_stub_open(struct inode *inode, struct file *filp); -extern int drm_fasync(int fd, struct file *filp, int on); extern ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); extern int drm_release(struct inode *inode, struct file *filp); -- cgit v1.2.3-70-g09d2 From 7d14bb6b537414ffe6a8641cb14088465c28460d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 8 Aug 2013 15:41:15 +0200 Subject: drm: don't call ->firstopen for KMS drivers It has way too much potential for driver writers to do stupid things like delayed hw setup because the load sequence is somehow racy (e.g. the imx driver in staging). So don't call it for modesetting drivers, which reduces the complexity of the drm core -> driver interface a notch. v2: Don't forget to update DocBook. v3: Go with Laurent's slightly more elaborate proposal for the DocBook update. Add a few words on top of his diff to elaborate a bit on what KMS drivers should and shouldn't do in lastclose. There was already a paragraph present talking about restoring properties, I've simply extended that one. Cc: Laurent Pinchart Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- Documentation/DocBook/drm.tmpl | 27 ++++++++++++++++----------- drivers/gpu/drm/drm_fops.c | 3 ++- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 6869b9b534b..9fc8ed4ac0f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2405,18 +2405,18 @@ void (*postclose) (struct drm_device *, struct drm_file *); The firstopen method is called by the DRM core - when an application opens a device that has no other opened file handle. - Similarly the lastclose method is called when - the last application holding a file handle opened on the device closes - it. Both methods are mostly used for UMS (User Mode Setting) drivers to - acquire and release device resources which should be done in the - load and unload - methods for KMS drivers. + for legacy UMS (User Mode Setting) drivers only when an application + opens a device that has no other opened file handle. UMS drivers can + implement it to acquire device resources. KMS drivers can't use the + method and must acquire resources in the load + method instead. - Note that the lastclose method is also called - at module unload time or, for hot-pluggable devices, when the device is - unplugged. The firstopen and + Similarly the lastclose method is called when + the last application holding a file handle opened on the device closes + it, for both UMS and KMS drivers. Additionally, the method is also + called at module unload time or, for hot-pluggable devices, when the + device is unplugged. The firstopen and lastclose calls can thus be unbalanced. @@ -2445,7 +2445,12 @@ void (*postclose) (struct drm_device *, struct drm_file *); The lastclose method should restore CRTC and plane properties to default value, so that a subsequent open of the - device will not inherit state from the previous user. + device will not inherit state from the previous user. It can also be + used to execute delayed power switching state changes, e.g. in + conjunction with the vga-switcheroo infrastructure. Beyond that KMS + drivers should not do any further cleanup. Only legacy UMS drivers might + need to clean up device state so that the vga console or an independent + fbdev driver could take over. diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 1817f03efe8..567997116d7 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -51,7 +51,8 @@ static int drm_setup(struct drm_device * dev) int i; int ret; - if (dev->driver->firstopen) { + if (dev->driver->firstopen && + !drm_core_check_feature(dev, DRIVER_MODESET)) { ret = dev->driver->firstopen(dev); if (ret != 0) return ret; -- cgit v1.2.3-70-g09d2 From f336ab76008f66f6153573d1479aeed388d7b08a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 8 Aug 2013 15:41:35 +0200 Subject: drm: move dev data clearing from drm_setup to lastclose We kzalloc this structure, and for real kms devices we should never loose track of things really. But ums/legacy drivers rely on the drm core to clean up a bit of cruft between lastclose and firstopen (i.e. when X is being restarted), so keep this around. But give it a clear drm_legacy_ prefix and conditionalize the code on !DRIVER_MODESET. Cc: David Herrmann Signed-off-by: Daniel Vetter Reviewed-by: David Herrmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/drm_fops.c | 27 +++------------------------ 2 files changed, 30 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index cf40be42baf..288da3dc2a0 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -170,6 +170,31 @@ static const struct drm_ioctl_desc drm_ioctls[] = { #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) +/** + * drm_legacy_dev_reinit + * + * Reinitializes a legacy/ums drm device in it's lastclose function. + */ +static void drm_legacy_dev_reinit(struct drm_device *dev) +{ + int i; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + + for (i = 0; i < ARRAY_SIZE(dev->counts); i++) + atomic_set(&dev->counts[i], 0); + + dev->sigdata.lock = NULL; + + dev->context_flag = 0; + dev->last_context = 0; + dev->if_version = 0; +} + /** * Take down the DRM device. * @@ -209,6 +234,8 @@ int drm_lastclose(struct drm_device * dev) dev->dev_mapping = NULL; mutex_unlock(&dev->struct_mutex); + drm_legacy_dev_reinit(dev); + DRM_DEBUG("lastclose completed\n"); return 0; } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 567997116d7..59f45929109 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -48,7 +48,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp, static int drm_setup(struct drm_device * dev) { - int i; int ret; if (dev->driver->firstopen && @@ -58,32 +57,12 @@ static int drm_setup(struct drm_device * dev) return ret; } - atomic_set(&dev->ioctl_count, 0); - atomic_set(&dev->vma_count, 0); - - i = drm_legacy_dma_setup(dev); - if (i < 0) - return i; - - for (i = 0; i < ARRAY_SIZE(dev->counts); i++) - atomic_set(&dev->counts[i], 0); - - dev->sigdata.lock = NULL; + ret = drm_legacy_dma_setup(dev); + if (ret < 0) + return ret; - dev->context_flag = 0; - dev->last_context = 0; - dev->if_version = 0; DRM_DEBUG("\n"); - - /* - * The kernel's context could be created here, but is now created - * in drm_dma_enqueue. This is more resource-efficient for - * hardware that does not do DMA, but may mean that - * drm_select_queue fails between the time the interrupt is - * initialized and the time the queues are initialized. - */ - return 0; } -- cgit v1.2.3-70-g09d2 From 319c933c71f3dbdb2b3274d1634d3494c70efa06 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 15 Aug 2013 00:02:46 +0200 Subject: drm/prime: proper locking+refcounting for obj->dma_buf link The export dma-buf cache is semantically similar to an flink name. So semantically it makes sense to treat it the same and remove the name (i.e. the dma_buf pointer) and its references when the last gem handle disappears. Again we need to be careful, but double so: Not just could someone race and export with a gem close ioctl (so we need to recheck obj->handle_count again when assigning the new name), but multiple exports can also race against each another. This is prevented by holding the dev->object_name_lock across the entire section which touches obj->dma_buf. With the new scheme we also need to reinstate the obj->dma_buf link at import time (in case the only reference userspace has held in-between was through the dma-buf fd and not through any native gem handle). For simplicity we don't check whether it's a native object but unconditionally set up that link - with the new scheme of removing the obj->dma_buf reference when the last handle disappears we can do that. To make it clear that this is not just for exported buffers anymore als rename it from export_dma_buf to dma_buf. To make sure that now one can race a fd_to_handle or handle_to_fd with gem_close we use the same tricks as in flink of extending the dev->object_name_locking critical section. With this change we finally have a guaranteed 1:1 relationship (at least for native objects) between gem objects and dma-bufs, even accounting for races (which can happen since the dma-buf itself holds a reference while in-flight). This prevent igt/prime_self_import/export-vs-gem_close-race from Oopsing the kernel. There is still a leak though since the per-file priv dma-buf/handle cache handling is racy. That will be fixed in a later patch. v2: Remove the bogus dma_buf_put from the export_and_register_object failure path if we've raced with the handle count dropping to 0. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 1 + drivers/gpu/drm/drm_gem.c | 24 ++++++++++++++-- drivers/gpu/drm/drm_prime.c | 70 +++++++++++++++++++++++++++++++++++---------- include/drm/drmP.h | 12 ++++++-- 4 files changed, 87 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 59f45929109..2d2401e9c5a 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -486,6 +486,7 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->postclose) dev->driver->postclose(dev, file_priv); + if (drm_core_check_feature(dev, DRIVER_PRIME)) drm_prime_destroy_file_private(&file_priv->prime); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d47aa774d64..4b3c533be85 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -195,9 +195,14 @@ drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) drm_prime_remove_buf_handle(&filp->prime, obj->import_attach->dmabuf); } - if (obj->export_dma_buf) { + + /* + * Note: obj->dma_buf can't disappear as long as we still hold a + * handle reference in obj->handle_count. + */ + if (obj->dma_buf) { drm_prime_remove_buf_handle(&filp->prime, - obj->export_dma_buf); + obj->dma_buf); } } @@ -231,6 +236,15 @@ static void drm_gem_object_handle_free(struct drm_gem_object *obj) } } +static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj) +{ + /* Unbreak the reference cycle if we have an exported dma_buf. */ + if (obj->dma_buf) { + dma_buf_put(obj->dma_buf); + obj->dma_buf = NULL; + } +} + static void drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) { @@ -244,8 +258,10 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) */ mutex_lock(&obj->dev->object_name_lock); - if (--obj->handle_count == 0) + if (--obj->handle_count == 0) { drm_gem_object_handle_free(obj); + drm_gem_object_exported_dma_buf_free(obj); + } mutex_unlock(&obj->dev->object_name_lock); drm_gem_object_unreference_unlocked(obj); @@ -712,6 +728,8 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private) void drm_gem_object_release(struct drm_gem_object *obj) { + WARN_ON(obj->dma_buf); + if (obj->filp) fput(obj->filp); } diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 3d576018893..5e543e9264d 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -193,11 +193,8 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf) { struct drm_gem_object *obj = dma_buf->priv; - if (obj->export_dma_buf == dma_buf) { - /* drop the reference on the export fd holds */ - obj->export_dma_buf = NULL; - drm_gem_object_unreference_unlocked(obj); - } + /* drop the reference on the export fd holds */ + drm_gem_object_unreference_unlocked(obj); } EXPORT_SYMBOL(drm_gem_dmabuf_release); @@ -298,6 +295,37 @@ struct dma_buf *drm_gem_prime_export(struct drm_device *dev, } EXPORT_SYMBOL(drm_gem_prime_export); +static struct dma_buf *export_and_register_object(struct drm_device *dev, + struct drm_gem_object *obj, + uint32_t flags) +{ + struct dma_buf *dmabuf; + + /* prevent races with concurrent gem_close. */ + if (obj->handle_count == 0) { + dmabuf = ERR_PTR(-ENOENT); + return dmabuf; + } + + dmabuf = dev->driver->gem_prime_export(dev, obj, flags); + if (IS_ERR(dmabuf)) { + /* normally the created dma-buf takes ownership of the ref, + * but if that fails then drop the ref + */ + return dmabuf; + } + + /* + * Note that callers do not need to clean up the export cache + * since the check for obj->handle_count guarantees that someone + * will clean it up. + */ + obj->dma_buf = dmabuf; + get_dma_buf(obj->dma_buf); + + return dmabuf; +} + int drm_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd) @@ -313,15 +341,20 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, /* re-export the original imported object */ if (obj->import_attach) { dmabuf = obj->import_attach->dmabuf; + get_dma_buf(dmabuf); goto out_have_obj; } - if (obj->export_dma_buf) { - dmabuf = obj->export_dma_buf; + mutex_lock(&dev->object_name_lock); + if (obj->dma_buf) { + get_dma_buf(obj->dma_buf); + dmabuf = obj->dma_buf; + mutex_unlock(&dev->object_name_lock); goto out_have_obj; } - dmabuf = dev->driver->gem_prime_export(dev, obj, flags); + dmabuf = export_and_register_object(dev, obj, flags); + mutex_unlock(&dev->object_name_lock); if (IS_ERR(dmabuf)) { /* normally the created dma-buf takes ownership of the ref, * but if that fails then drop the ref @@ -329,14 +362,13 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, ret = PTR_ERR(dmabuf); goto out; } - obj->export_dma_buf = dmabuf; mutex_lock(&file_priv->prime.lock); /* if we've exported this buffer the cheat and add it to the import list * so we get the correct handle back */ ret = drm_prime_add_buf_handle(&file_priv->prime, - obj->export_dma_buf, handle); + dmabuf, handle); if (ret) goto fail_put_dmabuf; @@ -349,7 +381,6 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, return 0; out_have_obj: - get_dma_buf(dmabuf); ret = dma_buf_fd(dmabuf, flags); if (ret < 0) { dma_buf_put(dmabuf); @@ -365,8 +396,6 @@ fail_rm_handle: dmabuf); mutex_unlock(&file_priv->prime.lock); fail_put_dmabuf: - /* clear NOT to be checked when releasing dma_buf */ - obj->export_dma_buf = NULL; dma_buf_put(dmabuf); out: drm_gem_object_unreference_unlocked(obj); @@ -448,13 +477,22 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev, goto out_put; /* never seen this one, need to import */ + mutex_lock(&dev->object_name_lock); obj = dev->driver->gem_prime_import(dev, dma_buf); if (IS_ERR(obj)) { ret = PTR_ERR(obj); - goto out_put; + goto out_unlock; + } + + if (obj->dma_buf) { + WARN_ON(obj->dma_buf != dma_buf); + } else { + obj->dma_buf = dma_buf; + get_dma_buf(dma_buf); } - ret = drm_gem_handle_create(file_priv, obj, handle); + /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ + ret = drm_gem_handle_create_tail(file_priv, obj, handle); drm_gem_object_unreference_unlocked(obj); if (ret) goto out_put; @@ -475,6 +513,8 @@ fail: * to detach.. which seems ok.. */ drm_gem_handle_delete(file_priv, *handle); +out_unlock: + mutex_lock(&dev->object_name_lock); out_put: dma_buf_put(dma_buf); mutex_unlock(&file_priv->prime.lock); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 063eac31b97..a95db49b3f9 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -667,8 +667,16 @@ struct drm_gem_object { void *driver_private; - /* dma buf exported from this GEM object */ - struct dma_buf *export_dma_buf; + /** + * dma_buf - dma buf associated with this GEM object + * + * Pointer to the dma-buf associated with this gem object (either + * through importing or exporting). We break the resulting reference + * loop when the last gem handle for this object is released. + * + * Protected by obj->object_name_lock + */ + struct dma_buf *dma_buf; /** * import_attach - dma buf attachment backing this object -- cgit v1.2.3-70-g09d2 From 13bb9cc8726c716a7f271fc2c760ba15e1fdd38c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 12 Sep 2012 15:55:05 +1000 Subject: drm: allow open of dynamic off devices. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 2 +- include/drm/drmP.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 2d2401e9c5a..136c949307b 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -219,7 +219,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, return -EBUSY; /* No exclusive opens */ if (!drm_cpu_valid()) return -EINVAL; - if (dev->switch_power_state != DRM_SWITCH_POWER_ON) + if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF) return -EINVAL; DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 90833dccc91..0e3d51793b6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1220,6 +1220,7 @@ struct drm_device { #define DRM_SWITCH_POWER_ON 0 #define DRM_SWITCH_POWER_OFF 1 #define DRM_SWITCH_POWER_CHANGING 2 +#define DRM_SWITCH_POWER_DYNAMIC_OFF 3 static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature) -- cgit v1.2.3-70-g09d2 From 1793126fcebd7c18834f95d43b55e387a8803aa8 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 25 Aug 2013 18:29:00 +0200 Subject: drm: implement experimental render nodes Render nodes provide an API for userspace to use non-privileged GPU commands without any running DRM-Master. It is useful for offscreen rendering, GPGPU clients, and normal render clients which do not perform modesetting. Compared to legacy clients, render clients no longer need any authentication to perform client ioctls. Instead, user-space controls render/client access to GPUs via filesystem access-modes on the render-node. Once a render-node was opened, a client has full access to the client/render operations on the GPU. However, no modesetting or ioctls that affect global state are allowed on render nodes. To prevent privilege-escalation, drivers must explicitly state that they support render nodes. They must mark their render-only ioctls as DRM_RENDER_ALLOW so render clients can use them. Furthermore, they must support clients without any attached master. If filesystem access-modes are not enough for fine-grained access control to render nodes (very unlikely, considering the versaitlity of FS-ACLs), you may still fall-back to fd-passing from server to client (which allows arbitrary access-control). However, note that revoking access is currently impossible and unlikely to get implemented. Note: Render clients no longer have any associated DRM-Master as they are supposed to be independent of any server state. DRM core highly depends on file_priv->master to be non-NULL for modesetting/ctx/etc. commands. Therefore, drivers must be very careful to not require DRM-Master if they support DRIVER_RENDER. So far render-nodes are protected by "drm_rnodes". As long as this module-parameter is not set to 1, a driver will not create render nodes. This allows us to experiment with the API a bit before we stabilize it. v2: drop insecure GEM_FLINK to force use of dmabuf Signed-off-by: David Herrmann Signed-off-by: Dave Airlie --- Documentation/DocBook/drm.tmpl | 69 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_drv.c | 13 ++++---- drivers/gpu/drm/drm_fops.c | 14 ++++----- drivers/gpu/drm/drm_pci.c | 9 ++++++ drivers/gpu/drm/drm_platform.c | 9 ++++++ drivers/gpu/drm/drm_stub.c | 10 ++++++ drivers/gpu/drm/drm_usb.c | 9 ++++++ include/drm/drmP.h | 9 ++++++ 8 files changed, 129 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/drm_fops.c') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 9fc8ed4ac0f..ed1d6d28902 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -205,6 +205,12 @@ Driver implements DRM PRIME buffer sharing. + + DRIVER_RENDER + + Driver supports dedicated render nodes. + + @@ -2644,6 +2650,69 @@ int (*resume) (struct drm_device *); info, since man pages should cover the rest. + + + + Render nodes + + DRM core provides multiple character-devices for user-space to use. + Depending on which device is opened, user-space can perform a different + set of operations (mainly ioctls). The primary node is always created + and called card<num>. Additionally, a currently + unused control node, called controlD<num> is also + created. The primary node provides all legacy operations and + historically was the only interface used by userspace. With KMS, the + control node was introduced. However, the planned KMS control interface + has never been written and so the control node stays unused to date. + + + With the increased use of offscreen renderers and GPGPU applications, + clients no longer require running compositors or graphics servers to + make use of a GPU. But the DRM API required unprivileged clients to + authenticate to a DRM-Master prior to getting GPU access. To avoid this + step and to grant clients GPU access without authenticating, render + nodes were introduced. Render nodes solely serve render clients, that + is, no modesetting or privileged ioctls can be issued on render nodes. + Only non-global rendering commands are allowed. If a driver supports + render nodes, it must advertise it via the DRIVER_RENDER + DRM driver capability. If not supported, the primary node must be used + for render clients together with the legacy drmAuth authentication + procedure. + + + If a driver advertises render node support, DRM core will create a + separate render node called renderD<num>. There will + be one render node per device. No ioctls except PRIME-related ioctls + will be allowed on this node. Especially GEM_OPEN will be + explicitly prohibited. Render nodes are designed to avoid the + buffer-leaks, which occur if clients guess the flink names or mmap + offsets on the legacy interface. Additionally to this basic interface, + drivers must mark their driver-dependent render-only ioctls as + DRM_RENDER_ALLOW so render clients can use them. Driver + authors must be careful not to allow any privileged ioctls on render + nodes. + + + With render nodes, user-space can now control access to the render node + via basic file-system access-modes. A running graphics server which + authenticates clients on the privileged primary/legacy node is no longer + required. Instead, a client can open the render node and is immediately + granted GPU access. Communication between clients (or servers) is done + via PRIME. FLINK from render node to legacy node is not supported. New + clients must not use the insecure FLINK interface. + + + Besides dropping all modeset/global ioctls, render nodes also drop the + DRM-Master concept. There is no reason to associate render clients with + a DRM-Master as they are independent of any graphics server. Besides, + they must work without any running master, anyway. + Drivers must be able to run without a master object if they support + render nodes. If, on the other hand, a driver requires shared state + between clients which is visible to user-space and accessible beyond + open-file boundaries, they cannot support render nodes. + + + diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 288da3dc2a0..e572dd20bde 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -68,7 +68,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), @@ -130,14 +130,14 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), @@ -420,9 +420,10 @@ long drm_ioctl(struct file *filp, DRM_DEBUG("no function\n"); retcode = -EINVAL; } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || - ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || + ((ioctl->flags & DRM_AUTH) && !drm_is_render_client(file_priv) && !file_priv->authenticated) || ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) || - (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) { + (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL)) || + (!(ioctl->flags & DRM_RENDER_ALLOW) && drm_is_render_client(file_priv))) { retcode = -EACCES; } else { if (cmd & (IOC_IN | IOC_OUT)) { diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 136c949307b..4be8e09a32e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -262,10 +262,10 @@ static int drm_open_helper(struct inode *inode, struct file *filp, goto out_prime_destroy; } - - /* if there is no current master make this fd it */ + /* if there is no current master make this fd it, but do not create + * any master object for render clients */ mutex_lock(&dev->struct_mutex); - if (!priv->minor->master) { + 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) { @@ -303,12 +303,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp, goto out_close; } } - mutex_unlock(&dev->struct_mutex); - } else { + } else if (!drm_is_render_client(priv)) { /* get a reference to the master */ priv->master = drm_master_get(priv->minor->master); - mutex_unlock(&dev->struct_mutex); } + mutex_unlock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex); list_add(&priv->lhead, &dev->filelist); @@ -478,7 +477,8 @@ int drm_release(struct inode *inode, struct file *filp) iput(container_of(dev->dev_mapping, struct inode, i_data)); /* drop the reference held my the file priv */ - drm_master_put(&file_priv->master); + if (file_priv->master) + drm_master_put(&file_priv->master); file_priv->is_master = 0; list_del(&file_priv->lhead); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 3fca2db1c40..1f96cee6eee 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -354,6 +354,12 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, goto err_g2; } + if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { + ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); + if (ret) + goto err_g21; + } + if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) goto err_g3; @@ -383,6 +389,9 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, err_g4: drm_put_minor(&dev->primary); err_g3: + if (dev->render) + drm_put_minor(&dev->render); +err_g21: if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_put_minor(&dev->control); err_g2: diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 400024b6d51..f7a18c6ba4c 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -69,6 +69,12 @@ static int drm_get_platform_dev(struct platform_device *platdev, goto err_g1; } + if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { + ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); + if (ret) + goto err_g11; + } + ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); if (ret) goto err_g2; @@ -100,6 +106,9 @@ static int drm_get_platform_dev(struct platform_device *platdev, err_g3: drm_put_minor(&dev->primary); err_g2: + if (dev->render) + drm_put_minor(&dev->render); +err_g11: if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_put_minor(&dev->control); err_g1: diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index e30bb0d7c67..e7eb0276f7f 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -40,6 +40,9 @@ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); +unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */ +EXPORT_SYMBOL(drm_rnodes); + unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ EXPORT_SYMBOL(drm_vblank_offdelay); @@ -56,11 +59,13 @@ MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); MODULE_PARM_DESC(debug, "Enable debug output"); +MODULE_PARM_DESC(rnodes, "Enable experimental render nodes API"); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); module_param_named(debug, drm_debug, int, 0600); +module_param_named(rnodes, drm_rnodes, int, 0600); module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); @@ -446,6 +451,9 @@ void drm_put_dev(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_put_minor(&dev->control); + if (dev->render) + drm_put_minor(&dev->render); + if (driver->driver_features & DRIVER_GEM) drm_gem_destroy(dev); @@ -462,6 +470,8 @@ void drm_unplug_dev(struct drm_device *dev) /* for a USB device */ if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_unplug_minor(dev->control); + if (dev->render) + drm_unplug_minor(dev->render); drm_unplug_minor(dev->primary); mutex_lock(&drm_global_mutex); diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index 34a156f0c33..87664723b9c 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -33,6 +33,12 @@ int drm_get_usb_dev(struct usb_interface *interface, if (ret) goto err_g1; + if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) { + ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER); + if (ret) + goto err_g11; + } + ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); if (ret) goto err_g2; @@ -62,6 +68,9 @@ int drm_get_usb_dev(struct usb_interface *interface, err_g3: drm_put_minor(&dev->primary); err_g2: + if (dev->render) + drm_put_minor(&dev->render); +err_g11: drm_put_minor(&dev->control); err_g1: kfree(dev); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 0e3d51793b6..290734191f7 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -145,6 +145,7 @@ int drm_err(const char *func, const char *format, ...); #define DRIVER_GEM 0x1000 #define DRIVER_MODESET 0x2000 #define DRIVER_PRIME 0x4000 +#define DRIVER_RENDER 0x8000 #define DRIVER_BUS_PCI 0x1 #define DRIVER_BUS_PLATFORM 0x2 @@ -290,6 +291,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, #define DRM_ROOT_ONLY 0x4 #define DRM_CONTROL_ALLOW 0x8 #define DRM_UNLOCKED 0x10 +#define DRM_RENDER_ALLOW 0x20 struct drm_ioctl_desc { unsigned int cmd; @@ -1204,6 +1206,7 @@ struct drm_device { unsigned int agp_buffer_token; struct drm_minor *control; /**< Control node for card */ struct drm_minor *primary; /**< render type primary screen head */ + struct drm_minor *render; /**< render node for card */ struct drm_mode_config mode_config; /**< Current mode config */ @@ -1251,6 +1254,11 @@ static inline bool drm_modeset_is_locked(struct drm_device *dev) return mutex_is_locked(&dev->mode_config.mutex); } +static inline bool drm_is_render_client(struct drm_file *file_priv) +{ + return file_priv->minor->type == DRM_MINOR_RENDER; +} + /******************************************************************/ /** \name Internal function definitions */ /*@{*/ @@ -1450,6 +1458,7 @@ extern void drm_put_dev(struct drm_device *dev); extern int drm_put_minor(struct drm_minor **minor); extern void drm_unplug_dev(struct drm_device *dev); extern unsigned int drm_debug; +extern unsigned int drm_rnodes; extern unsigned int drm_vblank_offdelay; extern unsigned int drm_timestamp_precision; -- cgit v1.2.3-70-g09d2