162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright © 2019-2021 Intel Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <drm/ttm/ttm_placement.h> 762306a36Sopenharmony_ci#include <linux/scatterlist.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "gem/i915_gem_region.h" 1062306a36Sopenharmony_ci#include "intel_memory_region.h" 1162306a36Sopenharmony_ci#include "intel_region_ttm.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "mock_region.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic void mock_region_put_pages(struct drm_i915_gem_object *obj, 1662306a36Sopenharmony_ci struct sg_table *pages) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci i915_refct_sgt_put(obj->mm.rsgt); 1962306a36Sopenharmony_ci obj->mm.rsgt = NULL; 2062306a36Sopenharmony_ci intel_region_ttm_resource_free(obj->mm.region, obj->mm.res); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int mock_region_get_pages(struct drm_i915_gem_object *obj) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci struct sg_table *pages; 2662306a36Sopenharmony_ci int err; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci obj->mm.res = intel_region_ttm_resource_alloc(obj->mm.region, 2962306a36Sopenharmony_ci obj->bo_offset, 3062306a36Sopenharmony_ci obj->base.size, 3162306a36Sopenharmony_ci obj->flags); 3262306a36Sopenharmony_ci if (IS_ERR(obj->mm.res)) 3362306a36Sopenharmony_ci return PTR_ERR(obj->mm.res); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci obj->mm.rsgt = intel_region_ttm_resource_to_rsgt(obj->mm.region, 3662306a36Sopenharmony_ci obj->mm.res, 3762306a36Sopenharmony_ci obj->mm.region->min_page_size); 3862306a36Sopenharmony_ci if (IS_ERR(obj->mm.rsgt)) { 3962306a36Sopenharmony_ci err = PTR_ERR(obj->mm.rsgt); 4062306a36Sopenharmony_ci goto err_free_resource; 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci pages = &obj->mm.rsgt->table; 4462306a36Sopenharmony_ci __i915_gem_object_set_pages(obj, pages); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cierr_free_resource: 4962306a36Sopenharmony_ci intel_region_ttm_resource_free(obj->mm.region, obj->mm.res); 5062306a36Sopenharmony_ci return err; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic const struct drm_i915_gem_object_ops mock_region_obj_ops = { 5462306a36Sopenharmony_ci .name = "mock-region", 5562306a36Sopenharmony_ci .get_pages = mock_region_get_pages, 5662306a36Sopenharmony_ci .put_pages = mock_region_put_pages, 5762306a36Sopenharmony_ci .release = i915_gem_object_release_memory_region, 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic int mock_object_init(struct intel_memory_region *mem, 6162306a36Sopenharmony_ci struct drm_i915_gem_object *obj, 6262306a36Sopenharmony_ci resource_size_t offset, 6362306a36Sopenharmony_ci resource_size_t size, 6462306a36Sopenharmony_ci resource_size_t page_size, 6562306a36Sopenharmony_ci unsigned int flags) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci static struct lock_class_key lock_class; 6862306a36Sopenharmony_ci struct drm_i915_private *i915 = mem->i915; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (size > resource_size(&mem->region)) 7162306a36Sopenharmony_ci return -E2BIG; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci drm_gem_private_object_init(&i915->drm, &obj->base, size); 7462306a36Sopenharmony_ci i915_gem_object_init(obj, &mock_region_obj_ops, &lock_class, flags); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci obj->bo_offset = offset; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci i915_gem_object_init_memory_region(obj, mem); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic int mock_region_fini(struct intel_memory_region *mem) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci struct drm_i915_private *i915 = mem->i915; 9062306a36Sopenharmony_ci int instance = mem->instance; 9162306a36Sopenharmony_ci int ret; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ret = intel_region_ttm_fini(mem); 9462306a36Sopenharmony_ci ida_free(&i915->selftest.mock_region_instances, instance); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return ret; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic const struct intel_memory_region_ops mock_region_ops = { 10062306a36Sopenharmony_ci .init = intel_region_ttm_init, 10162306a36Sopenharmony_ci .release = mock_region_fini, 10262306a36Sopenharmony_ci .init_object = mock_object_init, 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct intel_memory_region * 10662306a36Sopenharmony_cimock_region_create(struct drm_i915_private *i915, 10762306a36Sopenharmony_ci resource_size_t start, 10862306a36Sopenharmony_ci resource_size_t size, 10962306a36Sopenharmony_ci resource_size_t min_page_size, 11062306a36Sopenharmony_ci resource_size_t io_start, 11162306a36Sopenharmony_ci resource_size_t io_size) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci int instance = ida_alloc_max(&i915->selftest.mock_region_instances, 11462306a36Sopenharmony_ci TTM_NUM_MEM_TYPES - TTM_PL_PRIV - 1, 11562306a36Sopenharmony_ci GFP_KERNEL); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (instance < 0) 11862306a36Sopenharmony_ci return ERR_PTR(instance); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return intel_memory_region_create(i915, start, size, min_page_size, 12162306a36Sopenharmony_ci io_start, io_size, 12262306a36Sopenharmony_ci INTEL_MEMORY_MOCK, instance, 12362306a36Sopenharmony_ci &mock_region_ops); 12462306a36Sopenharmony_ci} 125