1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include "i915_drv.h" 7 #include "i915_reg.h" 8 #include "intel_memory_region.h" 9 #include "intel_region_lmem.h" 10 #include "intel_region_ttm.h" 11 #include "gem/i915_gem_lmem.h" 12 #include "gem/i915_gem_region.h" 13 #include "gem/i915_gem_ttm.h" 14 #include "gt/intel_gt.h" 15 #include "gt/intel_gt_regs.h" 16 17 static int 18 region_lmem_release(struct intel_memory_region *mem) 19 { 20 int ret; 21 22 ret = intel_region_ttm_fini(mem); 23 io_mapping_fini(&mem->iomap); 24 25 return ret; 26 } 27 28 static int 29 region_lmem_init(struct intel_memory_region *mem) 30 { 31 int ret; 32 33 if (!io_mapping_init_wc(&mem->iomap, 34 mem->io_start, 35 mem->io_size)) 36 return -EIO; 37 38 ret = intel_region_ttm_init(mem); 39 if (ret) 40 goto out_no_buddy; 41 42 return 0; 43 44 out_no_buddy: 45 io_mapping_fini(&mem->iomap); 46 47 return ret; 48 } 49 50 static const struct intel_memory_region_ops intel_region_lmem_ops = { 51 .init = region_lmem_init, 52 .release = region_lmem_release, 53 .init_object = __i915_gem_ttm_object_init, 54 }; 55 56 static bool get_legacy_lowmem_region(struct intel_uncore *uncore, 57 u64 *start, u32 *size) 58 { 59 if (!IS_DG1_GRAPHICS_STEP(uncore->i915, STEP_A0, STEP_C0)) 60 return false; 61 62 *start = 0; 63 *size = SZ_1M; 64 65 drm_dbg(&uncore->i915->drm, "LMEM: reserved legacy low-memory [0x%llx-0x%llx]\n", 66 *start, *start + *size); 67 68 return true; 69 } 70 71 static int reserve_lowmem_region(struct intel_uncore *uncore, 72 struct intel_memory_region *mem) 73 { 74 u64 reserve_start; 75 u32 reserve_size; 76 int ret; 77 78 if (!get_legacy_lowmem_region(uncore, &reserve_start, &reserve_size)) 79 return 0; 80 81 ret = intel_memory_region_reserve(mem, reserve_start, reserve_size); 82 if (ret) 83 drm_err(&uncore->i915->drm, "LMEM: reserving low memory region failed\n"); 84 85 return ret; 86 } 87 88 static struct intel_memory_region *setup_lmem(struct intel_gt *gt) 89 { 90 struct drm_i915_private *i915 = gt->i915; 91 struct intel_uncore *uncore = gt->uncore; 92 struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 93 struct intel_memory_region *mem; 94 resource_size_t min_page_size; 95 resource_size_t io_start; 96 resource_size_t io_size; 97 resource_size_t lmem_size; 98 int err; 99 100 if (!IS_DGFX(i915)) 101 return ERR_PTR(-ENODEV); 102 103 if (HAS_FLAT_CCS(i915)) { 104 u64 tile_stolen, flat_ccs_base; 105 106 lmem_size = pci_resource_len(pdev, 2); 107 flat_ccs_base = intel_gt_read_register(gt, XEHPSDV_FLAT_CCS_BASE_ADDR); 108 flat_ccs_base = (flat_ccs_base >> XEHPSDV_CCS_BASE_SHIFT) * SZ_64K; 109 110 if (GEM_WARN_ON(lmem_size < flat_ccs_base)) 111 return ERR_PTR(-ENODEV); 112 113 tile_stolen = lmem_size - flat_ccs_base; 114 115 /* If the FLAT_CCS_BASE_ADDR register is not populated, flag an error */ 116 if (tile_stolen == lmem_size) 117 drm_err(&i915->drm, 118 "CCS_BASE_ADDR register did not have expected value\n"); 119 120 lmem_size -= tile_stolen; 121 } else { 122 /* Stolen starts from GSMBASE without CCS */ 123 lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE); 124 } 125 126 if (i915->params.lmem_size > 0) { 127 lmem_size = min_t(resource_size_t, lmem_size, 128 mul_u32_u32(i915->params.lmem_size, SZ_1M)); 129 } 130 131 io_start = pci_resource_start(pdev, 2); 132 io_size = min(pci_resource_len(pdev, 2), lmem_size); 133 if (!io_size) 134 return ERR_PTR(-ENODEV); 135 136 min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : 137 I915_GTT_PAGE_SIZE_4K; 138 mem = intel_memory_region_create(i915, 139 0, 140 lmem_size, 141 min_page_size, 142 io_start, 143 io_size, 144 INTEL_MEMORY_LOCAL, 145 0, 146 &intel_region_lmem_ops); 147 if (IS_ERR(mem)) 148 return mem; 149 150 err = reserve_lowmem_region(uncore, mem); 151 if (err) 152 goto err_region_put; 153 154 drm_dbg(&i915->drm, "Local memory: %pR\n", &mem->region); 155 drm_dbg(&i915->drm, "Local memory IO start: %pa\n", 156 &mem->io_start); 157 drm_info(&i915->drm, "Local memory IO size: %pa\n", 158 &mem->io_size); 159 drm_info(&i915->drm, "Local memory available: %pa\n", 160 &lmem_size); 161 162 return mem; 163 164 err_region_put: 165 intel_memory_region_destroy(mem); 166 return ERR_PTR(err); 167 } 168 169 struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt) 170 { 171 return setup_lmem(gt); 172 } 173