1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include <drm/drm_print.h> 7 8 #include "i915_drv.h" 9 #include "i915_pci.h" 10 #include "i915_reg.h" 11 #include "intel_memory_region.h" 12 #include "intel_pci_config.h" 13 #include "intel_region_lmem.h" 14 #include "intel_region_ttm.h" 15 #include "gem/i915_gem_lmem.h" 16 #include "gem/i915_gem_region.h" 17 #include "gem/i915_gem_ttm.h" 18 #include "gt/intel_gt.h" 19 #include "gt/intel_gt_mcr.h" 20 #include "gt/intel_gt_regs.h" 21 22 #ifdef CONFIG_64BIT 23 static void 24 _resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size) 25 { 26 struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 27 int bar_size = pci_rebar_bytes_to_size(size); 28 int ret; 29 30 ret = pci_resize_resource(pdev, resno, bar_size, 0); 31 if (ret) { 32 drm_info(&i915->drm, "Failed to resize BAR%d to %dM (%pe)\n", 33 resno, 1 << bar_size, ERR_PTR(ret)); 34 return; 35 } 36 37 drm_info(&i915->drm, "BAR%d resized to %dM\n", resno, 1 << bar_size); 38 } 39 40 static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) 41 { 42 struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 43 struct pci_bus *root = pdev->bus; 44 struct resource *root_res; 45 resource_size_t rebar_size; 46 resource_size_t current_size; 47 intel_wakeref_t wakeref; 48 u32 pci_cmd; 49 int i; 50 51 current_size = roundup_pow_of_two(pci_resource_len(pdev, GEN12_LMEM_BAR)); 52 53 if (i915->params.lmem_bar_size) { 54 rebar_size = i915->params.lmem_bar_size * (resource_size_t)SZ_1M; 55 if (rebar_size == current_size) 56 return; 57 58 if (!pci_rebar_size_supported(pdev, GEN12_LMEM_BAR, 59 pci_rebar_bytes_to_size(rebar_size)) || 60 rebar_size >= roundup_pow_of_two(lmem_size)) { 61 rebar_size = lmem_size; 62 63 drm_info(&i915->drm, 64 "Given bar size is not within supported size, setting it to default: %llu\n", 65 (u64)lmem_size >> 20); 66 } 67 } else { 68 rebar_size = current_size; 69 70 if (rebar_size != roundup_pow_of_two(lmem_size)) 71 rebar_size = lmem_size; 72 else 73 return; 74 } 75 76 /* Find out if root bus contains 64bit memory addressing */ 77 while (root->parent) 78 root = root->parent; 79 80 pci_bus_for_each_resource(root, root_res, i) { 81 if (root_res && root_res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) && 82 root_res->start > 0x100000000ull) 83 break; 84 } 85 86 /* pci_resize_resource will fail anyways */ 87 if (!root_res) { 88 drm_info(&i915->drm, "Can't resize LMEM BAR - platform support is missing\n"); 89 return; 90 } 91 92 /* 93 * Releasing forcewake during BAR resizing results in later forcewake 94 * ack timeouts and former can happen any time - it is asynchronous. 95 * Grabbing all forcewakes prevents it. 96 */ 97 with_intel_runtime_pm(i915->uncore.rpm, wakeref) { 98 intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL); 99 100 /* First disable PCI memory decoding references */ 101 pci_read_config_dword(pdev, PCI_COMMAND, &pci_cmd); 102 pci_write_config_dword(pdev, PCI_COMMAND, 103 pci_cmd & ~PCI_COMMAND_MEMORY); 104 105 _resize_bar(i915, GEN12_LMEM_BAR, rebar_size); 106 107 pci_assign_unassigned_bus_resources(pdev->bus); 108 pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd); 109 intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL); 110 } 111 } 112 #else 113 static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {} 114 #endif 115 116 static int 117 region_lmem_release(struct intel_memory_region *mem) 118 { 119 int ret; 120 121 ret = intel_region_ttm_fini(mem); 122 io_mapping_fini(&mem->iomap); 123 124 return ret; 125 } 126 127 static int 128 region_lmem_init(struct intel_memory_region *mem) 129 { 130 int ret; 131 132 if (!io_mapping_init_wc(&mem->iomap, 133 mem->io.start, 134 resource_size(&mem->io))) 135 return -EIO; 136 137 ret = intel_region_ttm_init(mem); 138 if (ret) 139 goto out_no_buddy; 140 141 return 0; 142 143 out_no_buddy: 144 io_mapping_fini(&mem->iomap); 145 146 return ret; 147 } 148 149 static const struct intel_memory_region_ops intel_region_lmem_ops = { 150 .init = region_lmem_init, 151 .release = region_lmem_release, 152 .init_object = __i915_gem_ttm_object_init, 153 }; 154 155 static bool get_legacy_lowmem_region(struct intel_uncore *uncore, 156 u64 *start, u32 *size) 157 { 158 if (!IS_DG1(uncore->i915)) 159 return false; 160 161 *start = 0; 162 *size = SZ_1M; 163 164 drm_dbg(&uncore->i915->drm, "LMEM: reserved legacy low-memory [0x%llx-0x%llx]\n", 165 *start, *start + *size); 166 167 return true; 168 } 169 170 static int reserve_lowmem_region(struct intel_uncore *uncore, 171 struct intel_memory_region *mem) 172 { 173 u64 reserve_start; 174 u32 reserve_size; 175 int ret; 176 177 if (!get_legacy_lowmem_region(uncore, &reserve_start, &reserve_size)) 178 return 0; 179 180 ret = intel_memory_region_reserve(mem, reserve_start, reserve_size); 181 if (ret) 182 drm_err(&uncore->i915->drm, "LMEM: reserving low memory region failed\n"); 183 184 return ret; 185 } 186 187 static struct intel_memory_region *setup_lmem(struct intel_gt *gt) 188 { 189 struct drm_i915_private *i915 = gt->i915; 190 struct intel_uncore *uncore = gt->uncore; 191 struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 192 struct intel_memory_region *mem; 193 resource_size_t min_page_size; 194 resource_size_t io_start; 195 resource_size_t io_size; 196 resource_size_t lmem_size; 197 int err; 198 199 if (!IS_DGFX(i915)) 200 return ERR_PTR(-ENODEV); 201 202 if (!i915_pci_resource_valid(pdev, GEN12_LMEM_BAR)) 203 return ERR_PTR(-ENXIO); 204 205 if (HAS_FLAT_CCS(i915)) { 206 resource_size_t lmem_range; 207 u64 tile_stolen, flat_ccs_base; 208 209 lmem_range = intel_gt_mcr_read_any(to_gt(i915), XEHP_TILE0_ADDR_RANGE) & 0xFFFF; 210 lmem_size = lmem_range >> XEHP_TILE_LMEM_RANGE_SHIFT; 211 lmem_size *= SZ_1G; 212 213 flat_ccs_base = intel_gt_mcr_read_any(gt, XEHP_FLAT_CCS_BASE_ADDR); 214 flat_ccs_base = (flat_ccs_base >> XEHP_CCS_BASE_SHIFT) * SZ_64K; 215 216 if (GEM_WARN_ON(lmem_size < flat_ccs_base)) 217 return ERR_PTR(-EIO); 218 219 tile_stolen = lmem_size - flat_ccs_base; 220 221 /* If the FLAT_CCS_BASE_ADDR register is not populated, flag an error */ 222 if (tile_stolen == lmem_size) 223 drm_err(&i915->drm, 224 "CCS_BASE_ADDR register did not have expected value\n"); 225 226 lmem_size -= tile_stolen; 227 } else { 228 /* Stolen starts from GSMBASE without CCS */ 229 lmem_size = intel_uncore_read64(&i915->uncore, GEN6_GSMBASE); 230 } 231 232 i915_resize_lmem_bar(i915, lmem_size); 233 234 if (i915->params.lmem_size > 0) { 235 lmem_size = min_t(resource_size_t, lmem_size, 236 mul_u32_u32(i915->params.lmem_size, SZ_1M)); 237 } 238 239 io_start = pci_resource_start(pdev, GEN12_LMEM_BAR); 240 io_size = min(pci_resource_len(pdev, GEN12_LMEM_BAR), lmem_size); 241 if (!io_size) 242 return ERR_PTR(-EIO); 243 244 min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : 245 I915_GTT_PAGE_SIZE_4K; 246 mem = intel_memory_region_create(i915, 247 0, 248 lmem_size, 249 min_page_size, 250 io_start, 251 io_size, 252 INTEL_MEMORY_LOCAL, 253 0, 254 &intel_region_lmem_ops); 255 if (IS_ERR(mem)) 256 return mem; 257 258 err = reserve_lowmem_region(uncore, mem); 259 if (err) 260 goto err_region_put; 261 262 if (io_size < lmem_size) 263 drm_info(&i915->drm, "Using a reduced BAR size of %lluMiB. Consider enabling 'Resizable BAR' or similar, if available in the BIOS.\n", 264 (u64)io_size >> 20); 265 266 return mem; 267 268 err_region_put: 269 intel_memory_region_destroy(mem); 270 return ERR_PTR(err); 271 } 272 273 struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt) 274 { 275 return setup_lmem(gt); 276 } 277