Maarten Lankhorst
2012-Oct-12 15:06 UTC
[Nouveau] [PATCH 1/3] drm/nouveau: add reservation to nouveau_gem_ioctl_cpu_prep
Apart from some code inside ttm itself and nouveau_bo_vma_del,
this is the only place where ttm_bo_wait is used without a reservation.
Fix this so we can remove the fence_lock later on.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
---
drivers/gpu/drm/nouveau/nouveau_gem.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c
b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 5e2f521..18342b0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -837,17 +837,31 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void
*data,
struct drm_gem_object *gem;
struct nouveau_bo *nvbo;
bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
- int ret = -EINVAL;
+ int ret;
+ struct nouveau_fence *fence = NULL;
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
if (!gem)
return -ENOENT;
nvbo = nouveau_gem_object(gem);
- spin_lock(&nvbo->bo.bdev->fence_lock);
- ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait);
- spin_unlock(&nvbo->bo.bdev->fence_lock);
+ ret = ttm_bo_reserve(&nvbo->bo, true, false, false, 0);
+ if (!ret) {
+ spin_lock(&nvbo->bo.bdev->fence_lock);
+ ret = ttm_bo_wait(&nvbo->bo, true, true, true);
+ if (!no_wait && ret)
+ fence = nouveau_fence_ref(nvbo->bo.sync_obj);
+ spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+ ttm_bo_unreserve(&nvbo->bo);
+ }
drm_gem_object_unreference_unlocked(gem);
+
+ if (fence) {
+ ret = nouveau_fence_wait(fence, true, no_wait);
+ nouveau_fence_unref(&fence);
+ }
+
return ret;
}
Thomas Hellstrom
2012-Oct-18 16:30 UTC
[Nouveau] [PATCH 1/3] drm/nouveau: add reservation to nouveau_gem_ioctl_cpu_prep
So this is a typical case where a NO_WAIT can indeed become a WAIT because of the use of a reservation instead of a spinlock. (See the remove_fence_lock discussion) /Thomas On 10/12/2012 05:06 PM, Maarten Lankhorst wrote:> Apart from some code inside ttm itself and nouveau_bo_vma_del, > this is the only place where ttm_bo_wait is used without a reservation. > Fix this so we can remove the fence_lock later on. > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst at canonical.com> > --- > drivers/gpu/drm/nouveau/nouveau_gem.c | 22 ++++++++++++++++++---- > 1 file changed, 18 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c > index 5e2f521..18342b0 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_gem.c > +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c > @@ -837,17 +837,31 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, > struct drm_gem_object *gem; > struct nouveau_bo *nvbo; > bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); > - int ret = -EINVAL; > + int ret; > + struct nouveau_fence *fence = NULL; > > gem = drm_gem_object_lookup(dev, file_priv, req->handle); > if (!gem) > return -ENOENT; > nvbo = nouveau_gem_object(gem); > > - spin_lock(&nvbo->bo.bdev->fence_lock); > - ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait); > - spin_unlock(&nvbo->bo.bdev->fence_lock); > + ret = ttm_bo_reserve(&nvbo->bo, true, false, false, 0); > + if (!ret) { > + spin_lock(&nvbo->bo.bdev->fence_lock); > + ret = ttm_bo_wait(&nvbo->bo, true, true, true); > + if (!no_wait && ret) > + fence = nouveau_fence_ref(nvbo->bo.sync_obj); > + spin_unlock(&nvbo->bo.bdev->fence_lock); > + > + ttm_bo_unreserve(&nvbo->bo); > + } > drm_gem_object_unreference_unlocked(gem); > + > + if (fence) { > + ret = nouveau_fence_wait(fence, true, no_wait); > + nouveau_fence_unref(&fence); > + } > + > return ret; > } > > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel