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 lmem_size; 97 int err; 98 99 if (!IS_DGFX(i915)) 100 return ERR_PTR(-ENODEV); 101 102 if (HAS_FLAT_CCS(i915)) { 103 u64 tile_stolen, flat_ccs_base; 104 105 lmem_size = pci_resource_len(pdev, 2); 106 flat_ccs_base = intel_gt_read_register(gt, XEHPSDV_FLAT_CCS_BASE_ADDR); 107 flat_ccs_base = (flat_ccs_base >> XEHPSDV_CCS_BASE_SHIFT) * SZ_64K; 108 109 if (GEM_WARN_ON(lmem_size < flat_ccs_base)) 110 return ERR_PTR(-ENODEV); 111 112 tile_stolen = lmem_size - flat_ccs_base; 113 114 /* If the FLAT_CCS_BASE_ADDR register is not populated, flag an error */ 115 if (tile_stolen == lmem_size) 116 drm_err(&i915->drm, 117 "CCS_BASE_ADDR register did not have expected value\n"); 118 119 lmem_size -= tile_stolen; 120 } else { 121 /* Stolen starts from GSMBASE without CCS */ 122 lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE); 123 } 124 125 126 io_start = pci_resource_start(pdev, 2); 127 if (GEM_WARN_ON(lmem_size > pci_resource_len(pdev, 2))) 128 return ERR_PTR(-ENODEV); 129 130 min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : 131 I915_GTT_PAGE_SIZE_4K; 132 mem = intel_memory_region_create(i915, 133 0, 134 lmem_size, 135 min_page_size, 136 io_start, 137 lmem_size, 138 INTEL_MEMORY_LOCAL, 139 0, 140 &intel_region_lmem_ops); 141 if (IS_ERR(mem)) 142 return mem; 143 144 err = reserve_lowmem_region(uncore, mem); 145 if (err) 146 goto err_region_put; 147 148 drm_dbg(&i915->drm, "Local memory: %pR\n", &mem->region); 149 drm_dbg(&i915->drm, "Local memory IO start: %pa\n", 150 &mem->io_start); 151 drm_info(&i915->drm, "Local memory IO size: %pa\n", 152 &mem->io_size); 153 drm_info(&i915->drm, "Local memory available: %pa\n", 154 &lmem_size); 155 156 return mem; 157 158 err_region_put: 159 intel_memory_region_destroy(mem); 160 return ERR_PTR(err); 161 } 162 163 struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt) 164 { 165 return setup_lmem(gt); 166 } 167