drm/radeon/kms: implement bo busy check + current domain
This implements the busy ioctl along with a current domain check.
returns 0 or -EBUSY
puts the current domain no matter what the answer.
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 87170a5..79ad982 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -242,6 +242,7 @@
uint64_t *gpu_addr);
void radeon_object_unpin(struct radeon_object *robj);
int radeon_object_wait(struct radeon_object *robj);
+int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement);
int radeon_object_evict_vram(struct radeon_device *rdev);
int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset);
void radeon_object_force_delete(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index cded518..d4ceff1 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -262,7 +262,27 @@
int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
- /* FIXME: implement */
+ struct drm_radeon_gem_busy *args = data;
+ struct drm_gem_object *gobj;
+ struct radeon_object *robj;
+ int r;
+ uint32_t cur_placement;
+
+ gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ if (gobj == NULL) {
+ return -EINVAL;
+ }
+ robj = gobj->driver_private;
+ r = radeon_object_busy_domain(robj, &cur_placement);
+ if (cur_placement == TTM_PL_VRAM)
+ args->domain = RADEON_GEM_DOMAIN_VRAM;
+ if (cur_placement == TTM_PL_FLAG_TT)
+ args->domain = RADEON_GEM_DOMAIN_GTT;
+ if (cur_placement == TTM_PL_FLAG_SYSTEM)
+ args->domain = RADEON_GEM_DOMAIN_CPU;
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(gobj);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index e98cae3..b85fb83 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -316,6 +316,25 @@
return r;
}
+int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement)
+{
+ int r = 0;
+
+ r = radeon_object_reserve(robj, true);
+ if (unlikely(r != 0)) {
+ DRM_ERROR("radeon: failed to reserve object for waiting.\n");
+ return r;
+ }
+ spin_lock(&robj->tobj.lock);
+ *cur_placement = robj->tobj.mem.mem_type;
+ if (robj->tobj.sync_obj) {
+ r = ttm_bo_wait(&robj->tobj, true, true, true);
+ }
+ spin_unlock(&robj->tobj.lock);
+ radeon_object_unreserve(robj);
+ return r;
+}
+
int radeon_object_evict_vram(struct radeon_device *rdev)
{
if (rdev->flags & RADEON_IS_IGP) {
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index af4b482..f81c323 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -838,7 +838,7 @@
struct drm_radeon_gem_busy {
uint32_t handle;
- uint32_t busy;
+ uint32_t domain;
};
struct drm_radeon_gem_pread {