xref: /linux/drivers/gpu/drm/i915/gt/intel_region_lmem.c (revision 43dfc13ca972988e620a6edb72956981b75ab6b0)
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