drm/omap: add pin refcounting to omap_framebuffer
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Wed, 3 Sep 2014 19:25:54 +0000 (19:25 +0000)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Tue, 24 Mar 2015 11:33:25 +0000 (13:33 +0200)
omap_framebuffer_pin() and omap_framebuffer_unpin() are currently
broken, as they cannot be called multiple times (i.e. pin, pin, unpin,
unpin), which is what happens in certain cases. This issue causes the
driver to possibly use 0 as an address for a displayed buffer, leading
to OCP error from DSS.

This patch fixes the issue by adding a simple pin_count, used to track
the number of pins.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/omap_fb.c

index 45dd9eed9c57a80ea0b74986d1b962e94548dae6..d1e5f6da30d449df282b9c33246d9e7c594ededb 100644 (file)
@@ -86,6 +86,7 @@ struct plane {
 
 struct omap_framebuffer {
        struct drm_framebuffer base;
+       int pin_count;
        const struct format *format;
        struct plane planes[4];
 };
@@ -249,6 +250,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);
 
+       if (omap_fb->pin_count > 0) {
+               omap_fb->pin_count++;
+               return 0;
+       }
+
        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
                ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
@@ -257,6 +263,8 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)
                omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE);
        }
 
+       omap_fb->pin_count++;
+
        return 0;
 
 fail:
@@ -275,6 +283,11 @@ 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);
 
+       omap_fb->pin_count--;
+
+       if (omap_fb->pin_count > 0)
+               return 0;
+
        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
                ret = omap_gem_put_paddr(plane->bo);