Before atomic modesetting omap_framebuffer_pin() and
omap_framebuffer_unpin() were always called with modesetting locks
taken. With atomic modesetting support this is no longer the case, and
we need locking to protect the pin_count and the paddr, as multiple
threads may pin the same fb concurrently.

This patch adds a mutex to struct omap_framebuffer, and uses it in
omap_framebuffer_pin() and omap_framebuffer_unpin().

Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ti.com>
---
 drivers/gpu/drm/omapdrm/omap_fb.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c 
b/drivers/gpu/drm/omapdrm/omap_fb.c
index e505140a8782..0b967e76df1a 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -89,6 +89,8 @@ struct omap_framebuffer {
        int pin_count;
        const struct format *format;
        struct plane planes[4];
+       /* lock for pinning (pin_count and planes.paddr) */
+       struct mutex lock;
 };

 static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
@@ -250,8 +252,11 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
        int ret, i, n = drm_format_num_planes(fb->pixel_format);

+       mutex_lock(&omap_fb->lock);
+
        if (omap_fb->pin_count > 0) {
                omap_fb->pin_count++;
+               mutex_unlock(&omap_fb->lock);
                return 0;
        }

@@ -265,6 +270,8 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)

        omap_fb->pin_count++;

+       mutex_unlock(&omap_fb->lock);
+
        return 0;

 fail:
@@ -274,6 +281,8 @@ fail:
                plane->paddr = 0;
        }

+       mutex_unlock(&omap_fb->lock);
+
        return ret;
 }

@@ -283,10 +292,14 @@ int omap_framebuffer_unpin(struct drm_framebuffer *fb)
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
        int ret, i, n = drm_format_num_planes(fb->pixel_format);

+       mutex_lock(&omap_fb->lock);
+
        omap_fb->pin_count--;

-       if (omap_fb->pin_count > 0)
+       if (omap_fb->pin_count > 0) {
+               mutex_unlock(&omap_fb->lock);
                return 0;
+       }

        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
@@ -296,9 +309,12 @@ int omap_framebuffer_unpin(struct drm_framebuffer *fb)
                plane->paddr = 0;
        }

+       mutex_unlock(&omap_fb->lock);
+
        return 0;

 fail:
+       mutex_unlock(&omap_fb->lock);
        return ret;
 }

@@ -411,6 +427,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct 
drm_device *dev,

        fb = &omap_fb->base;
        omap_fb->format = format;
+       mutex_init(&omap_fb->lock);

        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
-- 
2.1.4

Reply via email to