18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: MIT 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright © 2019 Intel Corporation 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "i915_drv.h" 78c2ecf20Sopenharmony_ci#include "intel_memory_region.h" 88c2ecf20Sopenharmony_ci#include "gem/i915_gem_lmem.h" 98c2ecf20Sopenharmony_ci#include "gem/i915_gem_region.h" 108c2ecf20Sopenharmony_ci#include "intel_region_lmem.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic int init_fake_lmem_bar(struct intel_memory_region *mem) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci struct drm_i915_private *i915 = mem->i915; 158c2ecf20Sopenharmony_ci struct i915_ggtt *ggtt = &i915->ggtt; 168c2ecf20Sopenharmony_ci unsigned long n; 178c2ecf20Sopenharmony_ci int ret; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci /* We want to 1:1 map the mappable aperture to our reserved region */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci mem->fake_mappable.start = 0; 228c2ecf20Sopenharmony_ci mem->fake_mappable.size = resource_size(&mem->region); 238c2ecf20Sopenharmony_ci mem->fake_mappable.color = I915_COLOR_UNEVICTABLE; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci ret = drm_mm_reserve_node(&ggtt->vm.mm, &mem->fake_mappable); 268c2ecf20Sopenharmony_ci if (ret) 278c2ecf20Sopenharmony_ci return ret; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci mem->remap_addr = dma_map_resource(&i915->drm.pdev->dev, 308c2ecf20Sopenharmony_ci mem->region.start, 318c2ecf20Sopenharmony_ci mem->fake_mappable.size, 328c2ecf20Sopenharmony_ci PCI_DMA_BIDIRECTIONAL, 338c2ecf20Sopenharmony_ci DMA_ATTR_FORCE_CONTIGUOUS); 348c2ecf20Sopenharmony_ci if (dma_mapping_error(&i915->drm.pdev->dev, mem->remap_addr)) { 358c2ecf20Sopenharmony_ci drm_mm_remove_node(&mem->fake_mappable); 368c2ecf20Sopenharmony_ci return -EINVAL; 378c2ecf20Sopenharmony_ci } 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci for (n = 0; n < mem->fake_mappable.size >> PAGE_SHIFT; ++n) { 408c2ecf20Sopenharmony_ci ggtt->vm.insert_page(&ggtt->vm, 418c2ecf20Sopenharmony_ci mem->remap_addr + (n << PAGE_SHIFT), 428c2ecf20Sopenharmony_ci n << PAGE_SHIFT, 438c2ecf20Sopenharmony_ci I915_CACHE_NONE, 0); 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci mem->region = (struct resource)DEFINE_RES_MEM(mem->remap_addr, 478c2ecf20Sopenharmony_ci mem->fake_mappable.size); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic void release_fake_lmem_bar(struct intel_memory_region *mem) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci if (!drm_mm_node_allocated(&mem->fake_mappable)) 558c2ecf20Sopenharmony_ci return; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci drm_mm_remove_node(&mem->fake_mappable); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci dma_unmap_resource(&mem->i915->drm.pdev->dev, 608c2ecf20Sopenharmony_ci mem->remap_addr, 618c2ecf20Sopenharmony_ci mem->fake_mappable.size, 628c2ecf20Sopenharmony_ci PCI_DMA_BIDIRECTIONAL, 638c2ecf20Sopenharmony_ci DMA_ATTR_FORCE_CONTIGUOUS); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic void 678c2ecf20Sopenharmony_ciregion_lmem_release(struct intel_memory_region *mem) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci release_fake_lmem_bar(mem); 708c2ecf20Sopenharmony_ci io_mapping_fini(&mem->iomap); 718c2ecf20Sopenharmony_ci intel_memory_region_release_buddy(mem); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic int 758c2ecf20Sopenharmony_ciregion_lmem_init(struct intel_memory_region *mem) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci int ret; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (mem->i915->params.fake_lmem_start) { 808c2ecf20Sopenharmony_ci ret = init_fake_lmem_bar(mem); 818c2ecf20Sopenharmony_ci GEM_BUG_ON(ret); 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (!io_mapping_init_wc(&mem->iomap, 858c2ecf20Sopenharmony_ci mem->io_start, 868c2ecf20Sopenharmony_ci resource_size(&mem->region))) 878c2ecf20Sopenharmony_ci return -EIO; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci ret = intel_memory_region_init_buddy(mem); 908c2ecf20Sopenharmony_ci if (ret) 918c2ecf20Sopenharmony_ci io_mapping_fini(&mem->iomap); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci intel_memory_region_set_name(mem, "local"); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return ret; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciconst struct intel_memory_region_ops intel_region_lmem_ops = { 998c2ecf20Sopenharmony_ci .init = region_lmem_init, 1008c2ecf20Sopenharmony_ci .release = region_lmem_release, 1018c2ecf20Sopenharmony_ci .create_object = __i915_gem_lmem_object_create, 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistruct intel_memory_region * 1058c2ecf20Sopenharmony_ciintel_setup_fake_lmem(struct drm_i915_private *i915) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct pci_dev *pdev = i915->drm.pdev; 1088c2ecf20Sopenharmony_ci struct intel_memory_region *mem; 1098c2ecf20Sopenharmony_ci resource_size_t mappable_end; 1108c2ecf20Sopenharmony_ci resource_size_t io_start; 1118c2ecf20Sopenharmony_ci resource_size_t start; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci GEM_BUG_ON(i915_ggtt_has_aperture(&i915->ggtt)); 1148c2ecf20Sopenharmony_ci GEM_BUG_ON(!i915->params.fake_lmem_start); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* Your mappable aperture belongs to me now! */ 1178c2ecf20Sopenharmony_ci mappable_end = pci_resource_len(pdev, 2); 1188c2ecf20Sopenharmony_ci io_start = pci_resource_start(pdev, 2), 1198c2ecf20Sopenharmony_ci start = i915->params.fake_lmem_start; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci mem = intel_memory_region_create(i915, 1228c2ecf20Sopenharmony_ci start, 1238c2ecf20Sopenharmony_ci mappable_end, 1248c2ecf20Sopenharmony_ci PAGE_SIZE, 1258c2ecf20Sopenharmony_ci io_start, 1268c2ecf20Sopenharmony_ci &intel_region_lmem_ops); 1278c2ecf20Sopenharmony_ci if (!IS_ERR(mem)) { 1288c2ecf20Sopenharmony_ci drm_info(&i915->drm, "Intel graphics fake LMEM: %pR\n", 1298c2ecf20Sopenharmony_ci &mem->region); 1308c2ecf20Sopenharmony_ci drm_info(&i915->drm, 1318c2ecf20Sopenharmony_ci "Intel graphics fake LMEM IO start: %llx\n", 1328c2ecf20Sopenharmony_ci (u64)mem->io_start); 1338c2ecf20Sopenharmony_ci drm_info(&i915->drm, "Intel graphics fake LMEM size: %llx\n", 1348c2ecf20Sopenharmony_ci (u64)resource_size(&mem->region)); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return mem; 1388c2ecf20Sopenharmony_ci} 139