drm/nouveau: try to protect nbo->pin_refcount
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 11 Dec 2012 20:52:30 +0000 (21:52 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sun, 20 Jan 2013 14:57:56 +0000 (15:57 +0100)
... 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>
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_bo.h

index 69d7b1d0b9d69e2b24f27be89cc7f869669bd4a3..64d6e3047deec05c0c93f7f57b1c794b5bb2a041 100644 (file)
@@ -300,17 +300,18 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
        struct ttm_buffer_object *bo = &nvbo->bo;
        int ret;
 
+       ret = ttm_bo_reserve(bo, false, false, false, 0);
+       if (ret)
+               goto out;
+
        if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) {
                NV_ERROR(drm, "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo,
                         1 << bo->mem.mem_type, memtype);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        if (nvbo->pin_refcnt++)
-               return 0;
-
-       ret = ttm_bo_reserve(bo, false, false, false, 0);
-       if (ret)
                goto out;
 
        nouveau_bo_placement_set(nvbo, memtype, 0);
@@ -328,10 +329,8 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
                        break;
                }
        }
-       ttm_bo_unreserve(bo);
 out:
-       if (unlikely(ret))
-               nvbo->pin_refcnt--;
+       ttm_bo_unreserve(bo);
        return ret;
 }
 
@@ -342,13 +341,13 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
        struct ttm_buffer_object *bo = &nvbo->bo;
        int ret;
 
-       if (--nvbo->pin_refcnt)
-               return 0;
-
        ret = ttm_bo_reserve(bo, false, false, false, 0);
        if (ret)
                return ret;
 
+       if (--nvbo->pin_refcnt)
+               goto out;
+
        nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);
 
        ret = nouveau_bo_validate(nvbo, false, false);
@@ -365,6 +364,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
                }
        }
 
+out:
        ttm_bo_unreserve(bo);
        return ret;
 }
index 25ca37989d2cb24f128060453818b178d02551cb..81d00fe03b56bbe2099f430f913fee3f03f15de0 100644 (file)
@@ -28,6 +28,8 @@ struct nouveau_bo {
        struct nouveau_drm_tile *tile;
 
        struct drm_gem_object *gem;
+
+       /* protect by the ttm reservation lock */
        int pin_refcnt;
 
        struct ttm_bo_kmap_obj dma_buf_vmap;