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