[2/9] drm/radeon/kms: add support for new fault callback
diff mbox

Message ID 1266858699-23337-4-git-send-email-jglisse@redhat.com
State New, archived
Headers show

Commit Message

Jerome Glisse Feb. 22, 2010, 5:11 p.m. UTC
None

Patch
diff mbox

diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 1157e0f..b8c6567 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -434,10 +434,104 @@  static int radeon_bo_move(struct ttm_buffer_object *bo,
 memcpy:
 		r = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
 	}
-
 	return r;
 }
 
+static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, struct ttm_bus_placement *pl)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+	struct radeon_device *rdev = radeon_get_rdev(bdev);
+
+	pl->offset = mem->mm_node->start << PAGE_SHIFT;
+	pl->size = mem->num_pages << PAGE_SHIFT;
+	pl->base = 0;
+	pl->is_iomem = false;
+	if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+		return -EINVAL;
+	switch (mem->mem_type) {
+	case TTM_PL_SYSTEM:
+		/* system memory */
+		return 0;
+	case TTM_PL_TT:
+#if __OS_HAS_AGP
+		if (rdev->flags & RADEON_IS_AGP) {
+			/* RADEON_IS_AGP is set only if AGP is active */
+			pl->base = rdev->mc.agp_base;
+			pl->is_iomem = true;
+		}
+#endif
+		return 0;
+	case TTM_PL_VRAM:
+		/* check if it's visible */
+		if ((pl->offset + pl->size) > rdev->mc.visible_vram_size)
+			return -EINVAL;
+		pl->base = rdev->mc.aper_base;
+		pl->is_iomem = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void radeon_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+	/* hopefully will be usefull soon */
+}
+
+static int radeon_ttm_fault_callback(struct ttm_buffer_object *bo, struct ttm_bus_placement *pl)
+{
+	struct ttm_mem_type_manager *man = &bo->bdev->man[bo->mem.mem_type];
+	struct radeon_bo *rbo;
+	struct radeon_device *rdev;
+	int r;
+
+	pl->offset = bo->mem.mm_node->start << PAGE_SHIFT;
+	pl->size = bo->mem.num_pages << PAGE_SHIFT;
+	pl->base = 0;
+	pl->is_iomem = false;
+	if (!radeon_ttm_bo_is_radeon_bo(bo))
+		/* FIXME should we return 0 ? we don't know about this BO */
+		return -EINVAL;
+	if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+		return -EINVAL;
+	rbo = container_of(bo, struct radeon_bo, tbo);
+	rdev = rbo->rdev;
+	switch (bo->mem.mem_type) {
+	case TTM_PL_SYSTEM:
+		/* System memory */
+		return 0;
+	case TTM_PL_TT:
+#if __OS_HAS_AGP
+		if (rdev->flags & RADEON_IS_AGP) {
+			/* RADEON_IS_AGP is set only if AGP is active */
+			pl->base = rdev->mc.agp_base;
+			pl->is_iomem = true;
+		}
+#endif
+		return 0;
+	case TTM_PL_VRAM:
+		if ((pl->offset + pl->size) > rdev->mc.visible_vram_size) {
+			/* hurrah the memory is not visible ! */
+			radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
+			rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
+			r = ttm_bo_validate(bo, &rbo->placement, false, false);
+			if (unlikely(r != 0))
+				return r;
+			pl->offset = bo->mem.mm_node->start << PAGE_SHIFT;
+			/* this should not happen */
+			if ((pl->offset + pl->size) > rdev->mc.visible_vram_size)
+				return -EINVAL;
+		}
+		pl->base = rdev->mc.aper_base;
+		pl->is_iomem = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg,
 				bool lazy, bool interruptible)
 {
@@ -478,6 +572,9 @@  static struct ttm_bo_driver radeon_bo_driver = {
 	.sync_obj_ref = &radeon_sync_obj_ref,
 	.move_notify = &radeon_bo_move_notify,
 	.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
+	.fault_reserve = &radeon_ttm_fault_callback,
+	.io_mem_reserve = &radeon_ttm_io_mem_reserve,
+	.io_mem_free = &radeon_ttm_io_mem_free,
 };
 
 int radeon_ttm_init(struct radeon_device *rdev)