From 1c8887dd01d97781471c9a876e3a4e804bb33f31 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 2 Oct 2013 11:23:36 +0200 Subject: drm: move drm_lastclose() to drm_fops.c Try to keep all functions that handle DRM file_operations in drm_fops.c so internal helpers can be marked static later. This makes the split between the 3 core files more obvious: - drm_stub.c: DRM device allocation/destruction and management - drm_fops.c: DRM file_operations (except for ioctl) - drm_drv.c: Global DRM init + ioctl handling Well, ioctl handling is still spread throughout hundreds of source files, but at least the others are clearly defined this way. Signed-off-by: David Herrmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (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 3f84277d7036..8bc94eaaf9f5 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -385,6 +385,76 @@ static void drm_events_release(struct drm_file *file_priv) spin_unlock_irqrestore(&dev->event_lock, flags); } +/** + * 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. + * + * \param dev DRM device structure. + * + * Frees every resource in \p dev. + * + * \sa drm_device + */ +int drm_lastclose(struct drm_device * dev) +{ + struct drm_vma_entry *vma, *vma_temp; + + DRM_DEBUG("\n"); + + if (dev->driver->lastclose) + dev->driver->lastclose(dev); + DRM_DEBUG("driver lastclose completed\n"); + + if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET)) + drm_irq_uninstall(dev); + + mutex_lock(&dev->struct_mutex); + + drm_agp_clear(dev); + + drm_legacy_sg_cleanup(dev); + + /* Clear vma list (only built for debugging) */ + list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) { + list_del(&vma->head); + kfree(vma); + } + + drm_legacy_dma_takedown(dev); + + dev->dev_mapping = NULL; + mutex_unlock(&dev->struct_mutex); + + drm_legacy_dev_reinit(dev); + + DRM_DEBUG("lastclose completed\n"); + return 0; +} + /** * Release file. * -- cgit v1.2.3 From fc6ff1935b550bdf525e0caa5ef0894010375414 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 4 Oct 2013 14:53:39 +0300 Subject: drm: Kill ctx_count from struct drm_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only user of ctx_count is the via driver, and we can replace that use with list_is_singular(). Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_context.c | 2 -- drivers/gpu/drm/drm_fops.c | 1 - drivers/gpu/drm/via/via_mm.c | 2 +- include/drm/drmP.h | 1 - 4 files changed, 1 insertion(+), 5 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 224ff965bcf7..a4b017b6849e 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -334,7 +334,6 @@ int drm_addctx(struct drm_device *dev, void *data, mutex_lock(&dev->ctxlist_mutex); list_add(&ctx_entry->head, &dev->ctxlist); - ++dev->ctx_count; mutex_unlock(&dev->ctxlist_mutex); return 0; @@ -432,7 +431,6 @@ int drm_rmctx(struct drm_device *dev, void *data, if (pos->handle == ctx->handle) { list_del(&pos->head); kfree(pos); - --dev->ctx_count; } } } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 8bc94eaaf9f5..621b45e08bd1 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -524,7 +524,6 @@ int drm_release(struct inode *inode, struct file *filp) list_del(&pos->head); kfree(pos); - --dev->ctx_count; } } } diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index 7e3ad87c366c..927889105483 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -79,7 +79,7 @@ int via_final_context(struct drm_device *dev, int context) /* Linux specific until context tracking code gets ported to BSD */ /* Last context, perform cleanup */ - if (dev->ctx_count == 1 && dev->dev_private) { + if (list_is_singular(&dev->ctxlist) && dev->dev_private) { DRM_DEBUG("Last Context\n"); drm_irq_uninstall(dev); via_cleanup_futex(dev_priv); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 5b99c0e072ef..e26b80236719 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1132,7 +1132,6 @@ struct drm_device { /** \name Context handle management */ /*@{ */ struct list_head ctxlist; /**< Linked list of context handles */ - int ctx_count; /**< Number of context handles */ struct mutex ctxlist_mutex; /**< For ctxlist */ struct idr ctx_idr; -- cgit v1.2.3 From 0111be42186fc5461b9e9d579014c70869ab3152 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 4 Oct 2013 14:53:41 +0300 Subject: drm: Kill drm perf counter leftovers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The user of these counters was killed in commit d79cdc8312689b39c6d83718c1c196af4b3cd18c Author: Daniel Vetter Date: Thu Aug 8 15:41:32 2013 +0200 drm: no-op out GET_STATS ioctl so clean up the leftovers as well. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 1 - drivers/gpu/drm/drm_fops.c | 7 ------- drivers/gpu/drm/drm_lock.c | 3 --- drivers/gpu/drm/drm_stub.c | 9 --------- drivers/gpu/drm/i810/i810_dma.c | 11 ----------- drivers/gpu/drm/i915/i915_dma.c | 7 ------- drivers/gpu/drm/mga/mga_dma.c | 5 ----- include/drm/drmP.h | 7 ------- 8 files changed, 50 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 34d372ed904c..6495bdfd35dc 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -315,7 +315,6 @@ long drm_ioctl(struct file *filp, return -ENODEV; atomic_inc(&dev->ioctl_count); - atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); ++file_priv->ioctl_count; if ((nr >= DRM_CORE_IOCTL_COUNT) && diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 621b45e08bd1..d0e27667a4eb 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -113,7 +113,6 @@ int drm_open(struct inode *inode, struct file *filp) retcode = drm_open_helper(inode, filp, dev); if (retcode) goto err_undo; - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); if (need_setup) { retcode = drm_setup(dev); if (retcode) @@ -392,17 +391,12 @@ static void drm_events_release(struct drm_file *file_priv) */ 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; @@ -585,7 +579,6 @@ int drm_release(struct inode *inode, struct file *filp) * End inline drm_release */ - atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); if (!--dev->open_count) { if (atomic_read(&dev->ioctl_count)) { DRM_ERROR("Device busy: %d\n", diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index d752c96d6090..f6452682141b 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -86,7 +86,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) if (drm_lock_take(&master->lock, lock->context)) { master->lock.file_priv = file_priv; master->lock.lock_time = jiffies; - atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); break; /* Got lock */ } @@ -157,8 +156,6 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; } - atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); - if (drm_lock_free(&master->lock, lock->context)) { /* FIXME: Should really bail out here. */ } diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 2badef766d20..26055abf94ee 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -431,15 +431,6 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); - /* the DRM has 6 basic counters */ - dev->counters = 6; - dev->types[0] = _DRM_STAT_LOCK; - dev->types[1] = _DRM_STAT_OPENS; - dev->types[2] = _DRM_STAT_CLOSES; - dev->types[3] = _DRM_STAT_IOCTLS; - dev->types[4] = _DRM_STAT_LOCKS; - dev->types[5] = _DRM_STAT_UNLOCKS; - if (drm_ht_create(&dev->map_hash, 12)) goto err_free; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index ab1892eb1074..249fdff305c6 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -944,8 +944,6 @@ static int i810_dma_vertex(struct drm_device *dev, void *data, dma->buflist[vertex->idx], vertex->discard, vertex->used); - atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]); - atomic_inc(&dev->counts[_DRM_STAT_DMA]); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; @@ -1105,8 +1103,6 @@ static int i810_dma_mc(struct drm_device *dev, void *data, i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used, mc->last_render); - atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]); - atomic_inc(&dev->counts[_DRM_STAT_DMA]); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; @@ -1197,13 +1193,6 @@ static int i810_flip_bufs(struct drm_device *dev, void *data, int i810_driver_load(struct drm_device *dev, unsigned long flags) { - /* i810 has 4 more counters */ - dev->counters += 4; - dev->types[6] = _DRM_STAT_IRQ; - dev->types[7] = _DRM_STAT_PRIMARY; - dev->types[8] = _DRM_STAT_SECONDARY; - dev->types[9] = _DRM_STAT_DMA; - pci_set_master(dev->pdev); return 0; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d8478f7cdbf0..637b695eafbd 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1473,13 +1473,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET)) return -ENODEV; - /* i915 has 4 more counters */ - dev->counters += 4; - dev->types[6] = _DRM_STAT_IRQ; - dev->types[7] = _DRM_STAT_PRIMARY; - dev->types[8] = _DRM_STAT_SECONDARY; - dev->types[9] = _DRM_STAT_DMA; - dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index cc3166dd445a..087db33f6cff 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -406,11 +406,6 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); - dev->counters += 3; - dev->types[6] = _DRM_STAT_IRQ; - dev->types[7] = _DRM_STAT_PRIMARY; - dev->types[8] = _DRM_STAT_SECONDARY; - ret = drm_vblank_init(dev, 1); if (ret) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index a5d8024ad56d..9ba6a38f54be 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1115,13 +1115,6 @@ struct drm_device { atomic_t buf_alloc; /**< Buffer allocation in progress */ /*@} */ - /** \name Performance counters */ - /*@{ */ - unsigned long counters; - enum drm_stat_type types[15]; - atomic_t counts[15]; - /*@} */ - struct list_head filelist; /** \name Memory management */ -- cgit v1.2.3 From 1dda6805471d4120dba2fa0f2cc1053c2dab28de Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Tue, 29 Oct 2013 20:30:26 +0900 Subject: drm: delete unconsumed pending event list in drm_events_release When there are unconsumed pending events, the events are destroyed by calling destroy callback, but the events list are remained, because there is no list_del(). It is possible that the page flip request is handled after drm_events_release() is called and before drm_fb_release(). In this case a drm_pending_event is remained not freed. So exynos driver checks again to remove it in its post close routine. But the file_priv->event_list contains undeleted ones, this can make oops for accessing invalid memory. Signed-off-by: YoungJun Cho Signed-off-by: Kyungmin Park Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 4 +++- 1 file changed, 3 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 d0e27667a4eb..ee2d330a2fa0 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -378,8 +378,10 @@ static void drm_events_release(struct drm_file *file_priv) } /* Remove unconsumed events */ - list_for_each_entry_safe(e, et, &file_priv->event_list, link) + list_for_each_entry_safe(e, et, &file_priv->event_list, link) { + list_del(&e->link); e->destroy(e); + } spin_unlock_irqrestore(&dev->event_lock, flags); } -- cgit v1.2.3 From 1020dc6990168a5081ffad620c440e220f05b460 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 29 Oct 2013 08:55:57 +0000 Subject: drm: Do not drop root privileges for a fancier younger process When a second process opens the device and master transferrence is complete, we walk the list of open devices and remove their authentication. This also revokes our root privilege. Instead of simply dropping the authentication, this patch reverts the authenticated state back to its original value. Signed-off-by: Chris Wilson Reviewed-by: David Herrmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 5 +++-- include/drm/drmP.h | 1 + 2 files changed, 4 insertions(+), 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 ee2d330a2fa0..3a7176ce2540 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -239,7 +239,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->ioctl_count = 0; /* for compatibility root is always authenticated */ - priv->authenticated = capable(CAP_SYS_ADMIN); + priv->always_authenticated = capable(CAP_SYS_ADMIN); + priv->authenticated = priv->always_authenticated; priv->lock_count = 0; INIT_LIST_HEAD(&priv->lhead); @@ -533,7 +534,7 @@ int drm_release(struct inode *inode, struct file *filp) list_for_each_entry(temp, &dev->filelist, lhead) { if ((temp->master == file_priv->master) && (temp != file_priv)) - temp->authenticated = 0; + temp->authenticated = temp->always_authenticated; } /** diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 444751b9aa89..ea8bff3c8468 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -413,6 +413,7 @@ struct drm_prime_file_private { /** File private data */ struct drm_file { + int always_authenticated; int authenticated; struct pid *pid; kuid_t uid; -- cgit v1.2.3