]> git.ipfire.org Git - people/ms/linux.git/blame - drivers/gpu/drm/i915/gt/intel_region_lmem.c
Merge tag 'at91-fixes-6.0-2' of https://git.kernel.org/pub/scm/linux/kernel/git/at91...
[people/ms/linux.git] / drivers / gpu / drm / i915 / gt / intel_region_lmem.c
CommitLineData
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
19static 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
29static 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
49static 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
116static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {}
117#endif
a91d1a17 118
8b1f7f92 119static int
cb6d2467
AJ
120region_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
130static int
131region_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
146out_no_buddy:
147 io_mapping_fini(&mem->iomap);
cb6d2467
AJ
148
149 return ret;
150}
151
0dbfc194 152static 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
158static 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
173static 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
190static 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
276err_region_put:
8b1f7f92 277 intel_memory_region_destroy(mem);
7c5cc941 278 return ERR_PTR(err);
a50ca39f
MA
279}
280
281struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt)
282{
283 return setup_lmem(gt);
284}