]>
Commit | Line | Data |
---|---|---|
b908be54 MA |
1 | // SPDX-License-Identifier: MIT |
2 | /* | |
3 | * Copyright © 2019 Intel Corporation | |
4 | */ | |
5 | ||
6 | #include "i915_drv.h" | |
ce2fce25 | 7 | #include "i915_reg.h" |
b908be54 | 8 | #include "intel_memory_region.h" |
d1487389 TH |
9 | #include "intel_region_lmem.h" |
10 | #include "intel_region_ttm.h" | |
b908be54 MA |
11 | #include "gem/i915_gem_lmem.h" |
12 | #include "gem/i915_gem_region.h" | |
213d5092 | 13 | #include "gem/i915_gem_ttm.h" |
3ffe82d7 | 14 | #include "gt/intel_gt.h" |
e7858254 | 15 | #include "gt/intel_gt_mcr.h" |
30424eba | 16 | #include "gt/intel_gt_regs.h" |
b908be54 | 17 | |
9cae5b31 | 18 | #ifdef CONFIG_64BIT |
a91d1a17 AA |
19 | static void _release_bars(struct pci_dev *pdev) |
20 | { | |
21 | int resno; | |
22 | ||
23 | for (resno = PCI_STD_RESOURCES; resno < PCI_STD_RESOURCE_END; resno++) { | |
24 | if (pci_resource_len(pdev, resno)) | |
25 | pci_release_resource(pdev, resno); | |
26 | } | |
27 | } | |
28 | ||
29 | static void | |
30 | _resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size) | |
31 | { | |
32 | struct pci_dev *pdev = to_pci_dev(i915->drm.dev); | |
33 | int bar_size = pci_rebar_bytes_to_size(size); | |
34 | int ret; | |
35 | ||
36 | _release_bars(pdev); | |
37 | ||
38 | ret = pci_resize_resource(pdev, resno, bar_size); | |
39 | if (ret) { | |
40 | drm_info(&i915->drm, "Failed to resize BAR%d to %dM (%pe)\n", | |
41 | resno, 1 << bar_size, ERR_PTR(ret)); | |
42 | return; | |
43 | } | |
44 | ||
45 | drm_info(&i915->drm, "BAR%d resized to %dM\n", resno, 1 << bar_size); | |
46 | } | |
47 | ||
48 | #define LMEM_BAR_NUM 2 | |
49 | static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) | |
50 | { | |
51 | struct pci_dev *pdev = to_pci_dev(i915->drm.dev); | |
52 | struct pci_bus *root = pdev->bus; | |
53 | struct resource *root_res; | |
54 | resource_size_t rebar_size; | |
17cd10a4 | 55 | resource_size_t current_size; |
a91d1a17 AA |
56 | u32 pci_cmd; |
57 | int i; | |
58 | ||
17cd10a4 | 59 | current_size = roundup_pow_of_two(pci_resource_len(pdev, LMEM_BAR_NUM)); |
a91d1a17 | 60 | |
17cd10a4 PD |
61 | if (i915->params.lmem_bar_size) { |
62 | u32 bar_sizes; | |
63 | ||
64 | rebar_size = i915->params.lmem_bar_size * | |
65 | (resource_size_t)SZ_1M; | |
66 | bar_sizes = pci_rebar_get_possible_sizes(pdev, | |
67 | LMEM_BAR_NUM); | |
68 | ||
69 | if (rebar_size == current_size) | |
70 | return; | |
71 | ||
72 | if (!(bar_sizes & BIT(pci_rebar_bytes_to_size(rebar_size))) || | |
73 | rebar_size >= roundup_pow_of_two(lmem_size)) { | |
74 | rebar_size = lmem_size; | |
75 | ||
76 | drm_info(&i915->drm, | |
77 | "Given bar size is not within supported size, setting it to default: %llu\n", | |
78 | (u64)lmem_size >> 20); | |
79 | } | |
80 | } else { | |
81 | rebar_size = current_size; | |
82 | ||
83 | if (rebar_size != roundup_pow_of_two(lmem_size)) | |
84 | rebar_size = lmem_size; | |
85 | else | |
86 | return; | |
87 | } | |
a91d1a17 AA |
88 | |
89 | /* Find out if root bus contains 64bit memory addressing */ | |
90 | while (root->parent) | |
91 | root = root->parent; | |
92 | ||
93 | pci_bus_for_each_resource(root, root_res, i) { | |
94 | if (root_res && root_res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) && | |
95 | root_res->start > 0x100000000ull) | |
96 | break; | |
97 | } | |
98 | ||
99 | /* pci_resize_resource will fail anyways */ | |
100 | if (!root_res) { | |
101 | drm_info(&i915->drm, "Can't resize LMEM BAR - platform support is missing\n"); | |
102 | return; | |
103 | } | |
104 | ||
105 | /* First disable PCI memory decoding references */ | |
106 | pci_read_config_dword(pdev, PCI_COMMAND, &pci_cmd); | |
107 | pci_write_config_dword(pdev, PCI_COMMAND, | |
108 | pci_cmd & ~PCI_COMMAND_MEMORY); | |
109 | ||
110 | _resize_bar(i915, LMEM_BAR_NUM, rebar_size); | |
111 | ||
112 | pci_assign_unassigned_bus_resources(pdev->bus); | |
113 | pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd); | |
114 | } | |
9cae5b31 ND |
115 | #else |
116 | static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {} | |
117 | #endif | |
a91d1a17 | 118 | |
8b1f7f92 | 119 | static int |
cb6d2467 AJ |
120 | region_lmem_release(struct intel_memory_region *mem) |
121 | { | |
8b1f7f92 TH |
122 | int ret; |
123 | ||
124 | ret = intel_region_ttm_fini(mem); | |
cb6d2467 | 125 | io_mapping_fini(&mem->iomap); |
8b1f7f92 TH |
126 | |
127 | return ret; | |
cb6d2467 AJ |
128 | } |
129 | ||
130 | static int | |
131 | region_lmem_init(struct intel_memory_region *mem) | |
132 | { | |
133 | int ret; | |
134 | ||
135 | if (!io_mapping_init_wc(&mem->iomap, | |
136 | mem->io_start, | |
235582ca | 137 | mem->io_size)) |
8c26491f | 138 | return -EIO; |
cb6d2467 | 139 | |
d1487389 | 140 | ret = intel_region_ttm_init(mem); |
cb6d2467 | 141 | if (ret) |
d1487389 TH |
142 | goto out_no_buddy; |
143 | ||
144 | return 0; | |
145 | ||
146 | out_no_buddy: | |
147 | io_mapping_fini(&mem->iomap); | |
cb6d2467 AJ |
148 | |
149 | return ret; | |
150 | } | |
151 | ||
0dbfc194 | 152 | static const struct intel_memory_region_ops intel_region_lmem_ops = { |
cb6d2467 AJ |
153 | .init = region_lmem_init, |
154 | .release = region_lmem_release, | |
213d5092 | 155 | .init_object = __i915_gem_ttm_object_init, |
b908be54 | 156 | }; |
16292243 | 157 | |
7c5cc941 ID |
158 | static bool get_legacy_lowmem_region(struct intel_uncore *uncore, |
159 | u64 *start, u32 *size) | |
160 | { | |
c1f110ee | 161 | if (!IS_DG1_GRAPHICS_STEP(uncore->i915, STEP_A0, STEP_C0)) |
7c5cc941 ID |
162 | return false; |
163 | ||
164 | *start = 0; | |
165 | *size = SZ_1M; | |
166 | ||
167 | drm_dbg(&uncore->i915->drm, "LMEM: reserved legacy low-memory [0x%llx-0x%llx]\n", | |
168 | *start, *start + *size); | |
169 | ||
170 | return true; | |
171 | } | |
172 | ||
173 | static int reserve_lowmem_region(struct intel_uncore *uncore, | |
174 | struct intel_memory_region *mem) | |
175 | { | |
176 | u64 reserve_start; | |
177 | u32 reserve_size; | |
178 | int ret; | |
179 | ||
180 | if (!get_legacy_lowmem_region(uncore, &reserve_start, &reserve_size)) | |
181 | return 0; | |
182 | ||
183 | ret = intel_memory_region_reserve(mem, reserve_start, reserve_size); | |
184 | if (ret) | |
185 | drm_err(&uncore->i915->drm, "LMEM: reserving low memory region failed\n"); | |
186 | ||
187 | return ret; | |
188 | } | |
189 | ||
a50ca39f MA |
190 | static struct intel_memory_region *setup_lmem(struct intel_gt *gt) |
191 | { | |
192 | struct drm_i915_private *i915 = gt->i915; | |
7f2aa5b3 | 193 | struct intel_uncore *uncore = gt->uncore; |
97c463b2 | 194 | struct pci_dev *pdev = to_pci_dev(i915->drm.dev); |
a50ca39f | 195 | struct intel_memory_region *mem; |
ca921624 | 196 | resource_size_t min_page_size; |
a50ca39f | 197 | resource_size_t io_start; |
56eda725 | 198 | resource_size_t io_size; |
7f2aa5b3 | 199 | resource_size_t lmem_size; |
7c5cc941 | 200 | int err; |
a50ca39f MA |
201 | |
202 | if (!IS_DGFX(i915)) | |
203 | return ERR_PTR(-ENODEV); | |
204 | ||
4b31b8e3 | 205 | if (HAS_FLAT_CCS(i915)) { |
8f6de231 | 206 | resource_size_t lmem_range; |
4b31b8e3 AJ |
207 | u64 tile_stolen, flat_ccs_base; |
208 | ||
7d809707 MR |
209 | lmem_range = intel_gt_mcr_read_any(&i915->gt0, XEHP_TILE0_ADDR_RANGE) & 0xFFFF; |
210 | lmem_size = lmem_range >> XEHP_TILE_LMEM_RANGE_SHIFT; | |
8f6de231 ND |
211 | lmem_size *= SZ_1G; |
212 | ||
7d809707 MR |
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; | |
4b31b8e3 AJ |
215 | |
216 | if (GEM_WARN_ON(lmem_size < flat_ccs_base)) | |
d158367c | 217 | return ERR_PTR(-EIO); |
4b31b8e3 AJ |
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, GEN12_GSMBASE); | |
230 | } | |
231 | ||
a91d1a17 AA |
232 | i915_resize_lmem_bar(i915, lmem_size); |
233 | ||
be658e70 CT |
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 | } | |
7f2aa5b3 | 238 | |
a50ca39f | 239 | io_start = pci_resource_start(pdev, 2); |
56eda725 MA |
240 | io_size = min(pci_resource_len(pdev, 2), lmem_size); |
241 | if (!io_size) | |
d158367c | 242 | return ERR_PTR(-EIO); |
a50ca39f | 243 | |
ca921624 MA |
244 | min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : |
245 | I915_GTT_PAGE_SIZE_4K; | |
a50ca39f MA |
246 | mem = intel_memory_region_create(i915, |
247 | 0, | |
7f2aa5b3 | 248 | lmem_size, |
ca921624 | 249 | min_page_size, |
a50ca39f | 250 | io_start, |
56eda725 | 251 | io_size, |
d1487389 TH |
252 | INTEL_MEMORY_LOCAL, |
253 | 0, | |
a50ca39f MA |
254 | &intel_region_lmem_ops); |
255 | if (IS_ERR(mem)) | |
256 | return mem; | |
257 | ||
7c5cc941 ID |
258 | err = reserve_lowmem_region(uncore, mem); |
259 | if (err) | |
260 | goto err_region_put; | |
261 | ||
a50ca39f MA |
262 | drm_dbg(&i915->drm, "Local memory: %pR\n", &mem->region); |
263 | drm_dbg(&i915->drm, "Local memory IO start: %pa\n", | |
264 | &mem->io_start); | |
235582ca MA |
265 | drm_info(&i915->drm, "Local memory IO size: %pa\n", |
266 | &mem->io_size); | |
7f2aa5b3 CT |
267 | drm_info(&i915->drm, "Local memory available: %pa\n", |
268 | &lmem_size); | |
a50ca39f | 269 | |
eb1c535f MA |
270 | if (io_size < lmem_size) |
271 | drm_info(&i915->drm, "Using a reduced BAR size of %lluMiB. Consider enabling 'Resizable BAR' or similar, if available in the BIOS.\n", | |
272 | (u64)io_size >> 20); | |
273 | ||
a50ca39f | 274 | return mem; |
7c5cc941 ID |
275 | |
276 | err_region_put: | |
8b1f7f92 | 277 | intel_memory_region_destroy(mem); |
7c5cc941 | 278 | return ERR_PTR(err); |
a50ca39f MA |
279 | } |
280 | ||
281 | struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt) | |
282 | { | |
283 | return setup_lmem(gt); | |
284 | } |