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
_resize_bar(struct drm_i915_private * i915,int resno,resource_size_t size)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
i915_resize_lmem_bar(struct drm_i915_private * i915,resource_size_t lmem_size)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
i915_resize_lmem_bar(struct drm_i915_private * i915,resource_size_t lmem_size)113 static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {}
114 #endif
115
116 static int
region_lmem_release(struct intel_memory_region * mem)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
region_lmem_init(struct intel_memory_region * mem)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
get_legacy_lowmem_region(struct intel_uncore * uncore,u64 * start,u32 * size)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
reserve_lowmem_region(struct intel_uncore * uncore,struct intel_memory_region * mem)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
setup_lmem(struct intel_gt * gt)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
intel_gt_setup_lmem(struct intel_gt * gt)273 struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt)
274 {
275 return setup_lmem(gt);
276 }
277