xref: /openbmc/linux/drivers/gpu/drm/i915/gt/intel_region_lmem.c (revision 61c1f340bc809a1ca1e3c8794207a91cde1a7c78)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2019 Intel Corporation
4  */
5 
6 #include "i915_drv.h"
7 #include "i915_reg.h"
8 #include "intel_memory_region.h"
9 #include "intel_region_lmem.h"
10 #include "intel_region_ttm.h"
11 #include "gem/i915_gem_lmem.h"
12 #include "gem/i915_gem_region.h"
13 #include "gem/i915_gem_ttm.h"
14 #include "gt/intel_gt.h"
15 #include "gt/intel_gt_mcr.h"
16 #include "gt/intel_gt_regs.h"
17 
18 static int
19 region_lmem_release(struct intel_memory_region *mem)
20 {
21 	int ret;
22 
23 	ret = intel_region_ttm_fini(mem);
24 	io_mapping_fini(&mem->iomap);
25 
26 	return ret;
27 }
28 
29 static int
30 region_lmem_init(struct intel_memory_region *mem)
31 {
32 	int ret;
33 
34 	if (!io_mapping_init_wc(&mem->iomap,
35 				mem->io_start,
36 				mem->io_size))
37 		return -EIO;
38 
39 	ret = intel_region_ttm_init(mem);
40 	if (ret)
41 		goto out_no_buddy;
42 
43 	return 0;
44 
45 out_no_buddy:
46 	io_mapping_fini(&mem->iomap);
47 
48 	return ret;
49 }
50 
51 static const struct intel_memory_region_ops intel_region_lmem_ops = {
52 	.init = region_lmem_init,
53 	.release = region_lmem_release,
54 	.init_object = __i915_gem_ttm_object_init,
55 };
56 
57 static bool get_legacy_lowmem_region(struct intel_uncore *uncore,
58 				     u64 *start, u32 *size)
59 {
60 	if (!IS_DG1_GRAPHICS_STEP(uncore->i915, STEP_A0, STEP_C0))
61 		return false;
62 
63 	*start = 0;
64 	*size = SZ_1M;
65 
66 	drm_dbg(&uncore->i915->drm, "LMEM: reserved legacy low-memory [0x%llx-0x%llx]\n",
67 		*start, *start + *size);
68 
69 	return true;
70 }
71 
72 static int reserve_lowmem_region(struct intel_uncore *uncore,
73 				 struct intel_memory_region *mem)
74 {
75 	u64 reserve_start;
76 	u32 reserve_size;
77 	int ret;
78 
79 	if (!get_legacy_lowmem_region(uncore, &reserve_start, &reserve_size))
80 		return 0;
81 
82 	ret = intel_memory_region_reserve(mem, reserve_start, reserve_size);
83 	if (ret)
84 		drm_err(&uncore->i915->drm, "LMEM: reserving low memory region failed\n");
85 
86 	return ret;
87 }
88 
89 static struct intel_memory_region *setup_lmem(struct intel_gt *gt)
90 {
91 	struct drm_i915_private *i915 = gt->i915;
92 	struct intel_uncore *uncore = gt->uncore;
93 	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
94 	struct intel_memory_region *mem;
95 	resource_size_t min_page_size;
96 	resource_size_t io_start;
97 	resource_size_t io_size;
98 	resource_size_t lmem_size;
99 	int err;
100 
101 	if (!IS_DGFX(i915))
102 		return ERR_PTR(-ENODEV);
103 
104 	if (HAS_FLAT_CCS(i915)) {
105 		resource_size_t lmem_range;
106 		u64 tile_stolen, flat_ccs_base;
107 
108 		lmem_range = intel_gt_mcr_read_any(&i915->gt0, XEHP_TILE0_ADDR_RANGE) & 0xFFFF;
109 		lmem_size = lmem_range >> XEHP_TILE_LMEM_RANGE_SHIFT;
110 		lmem_size *= SZ_1G;
111 
112 		flat_ccs_base = intel_gt_mcr_read_any(gt, XEHP_FLAT_CCS_BASE_ADDR);
113 		flat_ccs_base = (flat_ccs_base >> XEHP_CCS_BASE_SHIFT) * SZ_64K;
114 
115 		/* FIXME: Remove this when we have small-bar enabled */
116 		if (pci_resource_len(pdev, 2) < lmem_size) {
117 			drm_err(&i915->drm, "System requires small-BAR support, which is currently unsupported on this kernel\n");
118 			return ERR_PTR(-EINVAL);
119 		}
120 
121 		if (GEM_WARN_ON(lmem_size < flat_ccs_base))
122 			return ERR_PTR(-EIO);
123 
124 		tile_stolen = lmem_size - flat_ccs_base;
125 
126 		/* If the FLAT_CCS_BASE_ADDR register is not populated, flag an error */
127 		if (tile_stolen == lmem_size)
128 			drm_err(&i915->drm,
129 				"CCS_BASE_ADDR register did not have expected value\n");
130 
131 		lmem_size -= tile_stolen;
132 	} else {
133 		/* Stolen starts from GSMBASE without CCS */
134 		lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE);
135 	}
136 
137 	if (i915->params.lmem_size > 0) {
138 		lmem_size = min_t(resource_size_t, lmem_size,
139 				  mul_u32_u32(i915->params.lmem_size, SZ_1M));
140 	}
141 
142 	io_start = pci_resource_start(pdev, 2);
143 	io_size = min(pci_resource_len(pdev, 2), lmem_size);
144 	if (!io_size)
145 		return ERR_PTR(-EIO);
146 
147 	min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K :
148 						I915_GTT_PAGE_SIZE_4K;
149 	mem = intel_memory_region_create(i915,
150 					 0,
151 					 lmem_size,
152 					 min_page_size,
153 					 io_start,
154 					 io_size,
155 					 INTEL_MEMORY_LOCAL,
156 					 0,
157 					 &intel_region_lmem_ops);
158 	if (IS_ERR(mem))
159 		return mem;
160 
161 	err = reserve_lowmem_region(uncore, mem);
162 	if (err)
163 		goto err_region_put;
164 
165 	drm_dbg(&i915->drm, "Local memory: %pR\n", &mem->region);
166 	drm_dbg(&i915->drm, "Local memory IO start: %pa\n",
167 		&mem->io_start);
168 	drm_info(&i915->drm, "Local memory IO size: %pa\n",
169 		 &mem->io_size);
170 	drm_info(&i915->drm, "Local memory available: %pa\n",
171 		 &lmem_size);
172 
173 	return mem;
174 
175 err_region_put:
176 	intel_memory_region_destroy(mem);
177 	return ERR_PTR(err);
178 }
179 
180 struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt)
181 {
182 	return setup_lmem(gt);
183 }
184