Reusing the Big DRM Lock just leaks, and the few things left that
dev->struct_mutex protected are very well contained - it's just the
linear drm_mm manager.

With this armada is completely struct_mutex free!

v2: Convert things properly and also take the lock in
armage_gem_free_object, and remove the stale comment (Russell).

Cc: Russell King <rmk+kernel at arm.linux.org.uk>
Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
---
 drivers/gpu/drm/armada/armada_debugfs.c |  4 ++--
 drivers/gpu/drm/armada/armada_drm.h     |  3 ++-
 drivers/gpu/drm/armada/armada_drv.c     |  1 +
 drivers/gpu/drm/armada/armada_gem.c     | 14 +++++++++-----
 4 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_debugfs.c 
b/drivers/gpu/drm/armada/armada_debugfs.c
index 471e45627f1e..d4f7ab0a30d4 100644
--- a/drivers/gpu/drm/armada/armada_debugfs.c
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -21,9 +21,9 @@ static int armada_debugfs_gem_linear_show(struct seq_file *m, 
void *data)
        struct armada_private *priv = dev->dev_private;
        int ret;

-       mutex_lock(&dev->struct_mutex);
+       mutex_lock(&priv->linear_lock);
        ret = drm_mm_dump_table(m, &priv->linear);
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&priv->linear_lock);

        return ret;
 }
diff --git a/drivers/gpu/drm/armada/armada_drm.h 
b/drivers/gpu/drm/armada/armada_drm.h
index 4df6f2af2b21..3b2bb6128d40 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -57,7 +57,8 @@ struct armada_private {
        DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
        struct drm_fb_helper    *fbdev;
        struct armada_crtc      *dcrtc[2];
-       struct drm_mm           linear;
+       struct drm_mm           linear; /* protected by linear_lock */
+       struct mutex            linear_lock;
        struct drm_property     *csc_yuv_prop;
        struct drm_property     *csc_rgb_prop;
        struct drm_property     *colorkey_prop;
diff --git a/drivers/gpu/drm/armada/armada_drv.c 
b/drivers/gpu/drm/armada/armada_drv.c
index 77ab93d60125..3bd7e1cde99e 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -102,6 +102,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned 
long flags)
        dev->mode_config.preferred_depth = 24;
        dev->mode_config.funcs = &armada_drm_mode_config_funcs;
        drm_mm_init(&priv->linear, mem->start, resource_size(mem));
+       mutex_init(&priv->linear_lock);

        ret = component_bind_all(dev->dev, dev);
        if (ret)
diff --git a/drivers/gpu/drm/armada/armada_gem.c 
b/drivers/gpu/drm/armada/armada_gem.c
index e3a86b96af2a..6e731db31aa4 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -46,22 +46,26 @@ static size_t roundup_gem_size(size_t size)
        return roundup(size, PAGE_SIZE);
 }

-/* dev->struct_mutex is held here */
 void armada_gem_free_object(struct drm_gem_object *obj)
 {
        struct armada_gem_object *dobj = drm_to_armada_gem(obj);
+       struct armada_private *priv = obj->dev->dev_private;

        DRM_DEBUG_DRIVER("release obj %p\n", dobj);

        drm_gem_free_mmap_offset(&dobj->obj);

+       might_lock(&priv->linear_lock);
+
        if (dobj->page) {
                /* page backed memory */
                unsigned int order = get_order(dobj->obj.size);
                __free_pages(dobj->page, order);
        } else if (dobj->linear) {
                /* linear backed memory */
+               mutex_lock(&priv->linear_lock);
                drm_mm_remove_node(dobj->linear);
+               mutex_unlock(&priv->linear_lock);
                kfree(dobj->linear);
                if (dobj->addr)
                        iounmap(dobj->addr);
@@ -144,10 +148,10 @@ armada_gem_linear_back(struct drm_device *dev, struct 
armada_gem_object *obj)
                if (!node)
                        return -ENOSPC;

-               mutex_lock(&dev->struct_mutex);
+               mutex_lock(&priv->linear_lock);
                ret = drm_mm_insert_node(&priv->linear, node, size, align,
                                         DRM_MM_SEARCH_DEFAULT);
-               mutex_unlock(&dev->struct_mutex);
+               mutex_unlock(&priv->linear_lock);
                if (ret) {
                        kfree(node);
                        return ret;
@@ -158,9 +162,9 @@ armada_gem_linear_back(struct drm_device *dev, struct 
armada_gem_object *obj)
                /* Ensure that the memory we're returning is cleared. */
                ptr = ioremap_wc(obj->linear->start, size);
                if (!ptr) {
-                       mutex_lock(&dev->struct_mutex);
+                       mutex_lock(&priv->linear_lock);
                        drm_mm_remove_node(obj->linear);
-                       mutex_unlock(&dev->struct_mutex);
+                       mutex_unlock(&priv->linear_lock);
                        kfree(obj->linear);
                        obj->linear = NULL;
                        return -ENOMEM;
-- 
2.5.1

Reply via email to