aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-12-11 15:52:30 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-20 09:57:56 -0500
commit0ae6d7bc0e70dafc1739d50b2b8d9d7c61968395 (patch)
tree34f34e14b0cf7cd9eb68cdb72cb63a3157889ab1
parent59ad1465423d968f06f243bc52cc3b1a320a27cf (diff)
drm/nouveau: try to protect nbo->pin_refcount
... by moving the bo_pin/bo_unpin manipulation of the pin_refcount under the protection of the ttm reservation lock. pin/unpin seems to get called from all over the place, so atm this is completely racy. After this patch there are only a few places in cleanup functions left which access ->pin_refcount without locking. But I'm hoping that those are safe and some other code invariant guarantees that this won't blow up. In any case, I only need to fix up pin/unpin to make ->pageflip work safely, so let's keep it at that. Add a comment to the header to explain the new locking rule. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c22
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.h2
2 files changed, 13 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 69d7b1d0b9d6..64d6e3047dee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -300,17 +300,18 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
300 struct ttm_buffer_object *bo = &nvbo->bo; 300 struct ttm_buffer_object *bo = &nvbo->bo;
301 int ret; 301 int ret;
302 302
303 ret = ttm_bo_reserve(bo, false, false, false, 0);
304 if (ret)
305 goto out;
306
303 if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) { 307 if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) {
304 NV_ERROR(drm, "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo, 308 NV_ERROR(drm, "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo,
305 1 << bo->mem.mem_type, memtype); 309 1 << bo->mem.mem_type, memtype);
306 return -EINVAL; 310 ret = -EINVAL;
311 goto out;
307 } 312 }
308 313
309 if (nvbo->pin_refcnt++) 314 if (nvbo->pin_refcnt++)
310 return 0;
311
312 ret = ttm_bo_reserve(bo, false, false, false, 0);
313 if (ret)
314 goto out; 315 goto out;
315 316
316 nouveau_bo_placement_set(nvbo, memtype, 0); 317 nouveau_bo_placement_set(nvbo, memtype, 0);
@@ -328,10 +329,8 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
328 break; 329 break;
329 } 330 }
330 } 331 }
331 ttm_bo_unreserve(bo);
332out: 332out:
333 if (unlikely(ret)) 333 ttm_bo_unreserve(bo);
334 nvbo->pin_refcnt--;
335 return ret; 334 return ret;
336} 335}
337 336
@@ -342,13 +341,13 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
342 struct ttm_buffer_object *bo = &nvbo->bo; 341 struct ttm_buffer_object *bo = &nvbo->bo;
343 int ret; 342 int ret;
344 343
345 if (--nvbo->pin_refcnt)
346 return 0;
347
348 ret = ttm_bo_reserve(bo, false, false, false, 0); 344 ret = ttm_bo_reserve(bo, false, false, false, 0);
349 if (ret) 345 if (ret)
350 return ret; 346 return ret;
351 347
348 if (--nvbo->pin_refcnt)
349 goto out;
350
352 nouveau_bo_placement_set(nvbo, bo->mem.placement, 0); 351 nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);
353 352
354 ret = nouveau_bo_validate(nvbo, false, false); 353 ret = nouveau_bo_validate(nvbo, false, false);
@@ -365,6 +364,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
365 } 364 }
366 } 365 }
367 366
367out:
368 ttm_bo_unreserve(bo); 368 ttm_bo_unreserve(bo);
369 return ret; 369 return ret;
370} 370}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h
index 25ca37989d2c..81d00fe03b56 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.h
@@ -28,6 +28,8 @@ struct nouveau_bo {
28 struct nouveau_drm_tile *tile; 28 struct nouveau_drm_tile *tile;
29 29
30 struct drm_gem_object *gem; 30 struct drm_gem_object *gem;
31
32 /* protect by the ttm reservation lock */
31 int pin_refcnt; 33 int pin_refcnt;
32 34
33 struct ttm_bo_kmap_obj dma_buf_vmap; 35 struct ttm_bo_kmap_obj dma_buf_vmap;