1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include "i915_drv.h" 7 #include "intel_memory_region.h" 8 #include "gem/i915_gem_lmem.h" 9 #include "gem/i915_gem_region.h" 10 #include "intel_region_lmem.h" 11 12 static int init_fake_lmem_bar(struct intel_memory_region *mem) 13 { 14 struct drm_i915_private *i915 = mem->i915; 15 struct i915_ggtt *ggtt = &i915->ggtt; 16 unsigned long n; 17 int ret; 18 19 /* We want to 1:1 map the mappable aperture to our reserved region */ 20 21 mem->fake_mappable.start = 0; 22 mem->fake_mappable.size = resource_size(&mem->region); 23 mem->fake_mappable.color = I915_COLOR_UNEVICTABLE; 24 25 ret = drm_mm_reserve_node(&ggtt->vm.mm, &mem->fake_mappable); 26 if (ret) 27 return ret; 28 29 mem->remap_addr = dma_map_resource(&i915->drm.pdev->dev, 30 mem->region.start, 31 mem->fake_mappable.size, 32 PCI_DMA_BIDIRECTIONAL, 33 DMA_ATTR_FORCE_CONTIGUOUS); 34 if (dma_mapping_error(&i915->drm.pdev->dev, mem->remap_addr)) { 35 drm_mm_remove_node(&mem->fake_mappable); 36 return -EINVAL; 37 } 38 39 for (n = 0; n < mem->fake_mappable.size >> PAGE_SHIFT; ++n) { 40 ggtt->vm.insert_page(&ggtt->vm, 41 mem->remap_addr + (n << PAGE_SHIFT), 42 n << PAGE_SHIFT, 43 I915_CACHE_NONE, 0); 44 } 45 46 mem->region = (struct resource)DEFINE_RES_MEM(mem->remap_addr, 47 mem->fake_mappable.size); 48 49 return 0; 50 } 51 52 static void release_fake_lmem_bar(struct intel_memory_region *mem) 53 { 54 if (!drm_mm_node_allocated(&mem->fake_mappable)) 55 return; 56 57 drm_mm_remove_node(&mem->fake_mappable); 58 59 dma_unmap_resource(&mem->i915->drm.pdev->dev, 60 mem->remap_addr, 61 mem->fake_mappable.size, 62 PCI_DMA_BIDIRECTIONAL, 63 DMA_ATTR_FORCE_CONTIGUOUS); 64 } 65 66 static void 67 region_lmem_release(struct intel_memory_region *mem) 68 { 69 release_fake_lmem_bar(mem); 70 io_mapping_fini(&mem->iomap); 71 intel_memory_region_release_buddy(mem); 72 } 73 74 static int 75 region_lmem_init(struct intel_memory_region *mem) 76 { 77 int ret; 78 79 if (mem->i915->params.fake_lmem_start) { 80 ret = init_fake_lmem_bar(mem); 81 GEM_BUG_ON(ret); 82 } 83 84 if (!io_mapping_init_wc(&mem->iomap, 85 mem->io_start, 86 resource_size(&mem->region))) 87 return -EIO; 88 89 ret = intel_memory_region_init_buddy(mem); 90 if (ret) 91 io_mapping_fini(&mem->iomap); 92 93 intel_memory_region_set_name(mem, "local"); 94 95 return ret; 96 } 97 98 static const struct intel_memory_region_ops intel_region_lmem_ops = { 99 .init = region_lmem_init, 100 .release = region_lmem_release, 101 .init_object = __i915_gem_lmem_object_init, 102 }; 103 104 struct intel_memory_region * 105 intel_setup_fake_lmem(struct drm_i915_private *i915) 106 { 107 struct pci_dev *pdev = i915->drm.pdev; 108 struct intel_memory_region *mem; 109 resource_size_t mappable_end; 110 resource_size_t io_start; 111 resource_size_t start; 112 113 GEM_BUG_ON(i915_ggtt_has_aperture(&i915->ggtt)); 114 GEM_BUG_ON(!i915->params.fake_lmem_start); 115 116 /* Your mappable aperture belongs to me now! */ 117 mappable_end = pci_resource_len(pdev, 2); 118 io_start = pci_resource_start(pdev, 2), 119 start = i915->params.fake_lmem_start; 120 121 mem = intel_memory_region_create(i915, 122 start, 123 mappable_end, 124 PAGE_SIZE, 125 io_start, 126 &intel_region_lmem_ops); 127 if (!IS_ERR(mem)) { 128 drm_info(&i915->drm, "Intel graphics fake LMEM: %pR\n", 129 &mem->region); 130 drm_info(&i915->drm, 131 "Intel graphics fake LMEM IO start: %llx\n", 132 (u64)mem->io_start); 133 drm_info(&i915->drm, "Intel graphics fake LMEM size: %llx\n", 134 (u64)resource_size(&mem->region)); 135 } 136 137 return mem; 138 } 139