File Index
Files and directories
Sign in
FILE

intel_region_lmem.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/gt/intel_region_lmem.c C
  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
 23static 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
 40static 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
113static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {}
114#endif
115
116static int
117region_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
127static int
128region_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
143out_no_buddy:
144	io_mapping_fini(&mem->iomap);
145
146	return ret;
147}
148
149static 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
155static 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
170static 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
187static 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
268err_region_put:
269	intel_memory_region_destroy(mem);
270	return ERR_PTR(err);
271}
272
273struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt)
274{
275	return setup_lmem(gt);
276}
~/ Read-only file preview.