diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-09-03 15:25:54 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-03-24 07:33:25 -0400 |
commit | f36eb5a899d3ea57e3d167427260848e116e27a0 (patch) | |
tree | f92b2050b1fc2b8341dec645071e34efa5faea1e /drivers/gpu/drm/omapdrm/omap_fb.c | |
parent | 3f4d17c4eca9769d56218a38dbfc482794fbde2f (diff) |
drm/omap: add pin refcounting to omap_framebuffer
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>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fb.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 45dd9eed9c57..d1e5f6da30d4 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c | |||
@@ -86,6 +86,7 @@ struct plane { | |||
86 | 86 | ||
87 | struct omap_framebuffer { | 87 | struct omap_framebuffer { |
88 | struct drm_framebuffer base; | 88 | struct drm_framebuffer base; |
89 | int pin_count; | ||
89 | const struct format *format; | 90 | const struct format *format; |
90 | struct plane planes[4]; | 91 | struct plane planes[4]; |
91 | }; | 92 | }; |
@@ -249,6 +250,11 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb) | |||
249 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); | 250 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); |
250 | int ret, i, n = drm_format_num_planes(fb->pixel_format); | 251 | int ret, i, n = drm_format_num_planes(fb->pixel_format); |
251 | 252 | ||
253 | if (omap_fb->pin_count > 0) { | ||
254 | omap_fb->pin_count++; | ||
255 | return 0; | ||
256 | } | ||
257 | |||
252 | for (i = 0; i < n; i++) { | 258 | for (i = 0; i < n; i++) { |
253 | struct plane *plane = &omap_fb->planes[i]; | 259 | struct plane *plane = &omap_fb->planes[i]; |
254 | ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true); | 260 | ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true); |
@@ -257,6 +263,8 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb) | |||
257 | omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE); | 263 | omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE); |
258 | } | 264 | } |
259 | 265 | ||
266 | omap_fb->pin_count++; | ||
267 | |||
260 | return 0; | 268 | return 0; |
261 | 269 | ||
262 | fail: | 270 | fail: |
@@ -275,6 +283,11 @@ int omap_framebuffer_unpin(struct drm_framebuffer *fb) | |||
275 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); | 283 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); |
276 | int ret, i, n = drm_format_num_planes(fb->pixel_format); | 284 | int ret, i, n = drm_format_num_planes(fb->pixel_format); |
277 | 285 | ||
286 | omap_fb->pin_count--; | ||
287 | |||
288 | if (omap_fb->pin_count > 0) | ||
289 | return 0; | ||
290 | |||
278 | for (i = 0; i < n; i++) { | 291 | for (i = 0; i < n; i++) { |
279 | struct plane *plane = &omap_fb->planes[i]; | 292 | struct plane *plane = &omap_fb->planes[i]; |
280 | ret = omap_gem_put_paddr(plane->bo); | 293 | ret = omap_gem_put_paddr(plane->bo); |