Buffer object idle and mapping synchronization.
parent
480ea65ee4
commit
05536a6478
|
@ -967,6 +967,7 @@ typedef struct drm_buffer_object{
|
||||||
drm_fence_object_t *fence;
|
drm_fence_object_t *fence;
|
||||||
int unfenced;
|
int unfenced;
|
||||||
wait_queue_head_t validate_queue;
|
wait_queue_head_t validate_queue;
|
||||||
|
struct mutex mutex;
|
||||||
} drm_buffer_object_t;
|
} drm_buffer_object_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,148 @@ int drm_bo_alloc_space(drm_device_t *dev, int tt, drm_buffer_object_t *buf)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call dev->struct_mutex locked.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
drm_buffer_object_t *drm_lookup_buffer_object(drm_file_t *priv, uint32_t handle,
|
||||||
|
int check_owner)
|
||||||
|
{
|
||||||
|
drm_user_object_t *uo;
|
||||||
|
drm_buffer_object_t *bo;
|
||||||
|
|
||||||
|
uo = drm_lookup_user_object(priv, handle);
|
||||||
|
|
||||||
|
if (!uo || (uo->type != drm_buffer_type))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (check_owner && priv != uo->owner) {
|
||||||
|
if (!drm_lookup_ref_object(priv, uo, _DRM_REF_USE))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
|
||||||
|
atomic_inc(&bo->usage);
|
||||||
|
return bo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call bo->mutex locked.
|
||||||
|
* Wait until the buffer is idle.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int drm_bo_wait(drm_device_t *dev, drm_buffer_object_t *bo, int lazy)
|
||||||
|
{
|
||||||
|
|
||||||
|
drm_fence_object_t *fence = bo->fence;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (fence) {
|
||||||
|
if (drm_fence_object_signaled(fence, bo->fence_flags)) {
|
||||||
|
drm_fence_usage_deref_unlocked(dev, fence);
|
||||||
|
bo->fence = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure another process doesn't destroy the fence
|
||||||
|
* object when we release the buffer object mutex.
|
||||||
|
* We don't need to take the dev->struct_mutex lock here,
|
||||||
|
* since the fence usage count is at least 1 already.
|
||||||
|
*/
|
||||||
|
|
||||||
|
atomic_inc(&fence->usage);
|
||||||
|
mutex_unlock(&bo->mutex);
|
||||||
|
ret = drm_fence_object_wait(dev, fence, lazy, !lazy, bo->fence_flags);
|
||||||
|
mutex_lock(&bo->mutex);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
drm_fence_usage_deref_locked(dev, fence);
|
||||||
|
if (bo->fence == fence) {
|
||||||
|
drm_fence_usage_deref_locked(dev, fence);
|
||||||
|
bo->fence = NULL;
|
||||||
|
}
|
||||||
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call bo->mutex locked.
|
||||||
|
* Returns 1 if the buffer is currently rendered to or from. 0 otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int drm_bo_busy(drm_device_t *dev, drm_buffer_object_t *bo)
|
||||||
|
{
|
||||||
|
drm_fence_object_t *fence = bo->fence;
|
||||||
|
|
||||||
|
if (fence) {
|
||||||
|
if (drm_fence_object_signaled(fence, bo->fence_flags)) {
|
||||||
|
drm_fence_usage_deref_unlocked(dev, fence);
|
||||||
|
bo->fence = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
drm_fence_object_flush(dev, fence, DRM_FENCE_EXE);
|
||||||
|
if (drm_fence_object_signaled(fence, bo->fence_flags)) {
|
||||||
|
drm_fence_usage_deref_unlocked(dev, fence);
|
||||||
|
bo->fence = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for buffer idle and register that we've mapped the buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int drm_buffer_object_map(drm_file_t *priv, uint32_t handle, int wait)
|
||||||
|
{
|
||||||
|
drm_buffer_object_t *bo;
|
||||||
|
drm_device_t *dev = priv->head->dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
bo = drm_lookup_buffer_object(priv, handle, 1);
|
||||||
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
|
if (!bo)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&bo->mutex);
|
||||||
|
|
||||||
|
if (!wait) {
|
||||||
|
if ((atomic_read(&bo->mapped) == 0) &&
|
||||||
|
drm_bo_busy(dev, bo)) {
|
||||||
|
mutex_unlock(&bo->mutex);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = drm_bo_wait(dev, bo, 0);
|
||||||
|
if (ret) {
|
||||||
|
mutex_unlock(&bo->mutex);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_lock(&dev->struct_mutex);
|
||||||
|
ret = drm_add_ref_object(priv, &bo->base, _DRM_REF_TYPE1);
|
||||||
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
if (!ret) {
|
||||||
|
atomic_inc(&bo->mapped);
|
||||||
|
}
|
||||||
|
mutex_unlock(&bo->mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int drm_bo_ioctl(DRM_IOCTL_ARGS)
|
int drm_bo_ioctl(DRM_IOCTL_ARGS)
|
||||||
{
|
{
|
||||||
DRM_DEVICE;
|
DRM_DEVICE;
|
||||||
|
@ -317,6 +459,11 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
|
||||||
rep.ret = 0;
|
rep.ret = 0;
|
||||||
rep.handled = 0;
|
rep.handled = 0;
|
||||||
switch (req->op) {
|
switch (req->op) {
|
||||||
|
case drm_bo_map:
|
||||||
|
rep.ret = drm_buffer_object_map(priv, req->handle,
|
||||||
|
!(req->hint &
|
||||||
|
DRM_BO_HINT_DONT_BLOCK));
|
||||||
|
break;
|
||||||
case drm_bo_destroy:
|
case drm_bo_destroy:
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
uo = drm_lookup_user_object(priv, req->handle);
|
uo = drm_lookup_user_object(priv, req->handle);
|
||||||
|
|
Loading…
Reference in New Issue