1f178b897SMatthew Auld // SPDX-License-Identifier: MIT
2f178b897SMatthew Auld /*
3f178b897SMatthew Auld * Copyright © 2019 Intel Corporation
4f178b897SMatthew Auld */
5f178b897SMatthew Auld
6f178b897SMatthew Auld #include "i915_drv.h"
71bba7323SPiotr Piórkowski #include "i915_pci.h"
8ce2fce25SMatt Roper #include "i915_reg.h"
9f178b897SMatthew Auld #include "intel_memory_region.h"
106bba2b30SPiotr Piórkowski #include "intel_pci_config.h"
11d1487389SThomas Hellström #include "intel_region_lmem.h"
12d1487389SThomas Hellström #include "intel_region_ttm.h"
13f178b897SMatthew Auld #include "gem/i915_gem_lmem.h"
14f178b897SMatthew Auld #include "gem/i915_gem_region.h"
15213d5092SThomas Hellström #include "gem/i915_gem_ttm.h"
163ffe82d7SDaniele Ceraolo Spurio #include "gt/intel_gt.h"
17e7858254SMatt Roper #include "gt/intel_gt_mcr.h"
1830424ebaSRodrigo Vivi #include "gt/intel_gt_regs.h"
19f178b897SMatthew Auld
209cae5b31SNirmoy Das #ifdef CONFIG_64BIT
_release_bars(struct pci_dev * pdev)21a91d1a17SAkeem G Abodunrin static void _release_bars(struct pci_dev *pdev)
22a91d1a17SAkeem G Abodunrin {
23a91d1a17SAkeem G Abodunrin int resno;
24a91d1a17SAkeem G Abodunrin
25a91d1a17SAkeem G Abodunrin for (resno = PCI_STD_RESOURCES; resno < PCI_STD_RESOURCE_END; resno++) {
26a91d1a17SAkeem G Abodunrin if (pci_resource_len(pdev, resno))
27a91d1a17SAkeem G Abodunrin pci_release_resource(pdev, resno);
28a91d1a17SAkeem G Abodunrin }
29a91d1a17SAkeem G Abodunrin }
30a91d1a17SAkeem G Abodunrin
31a91d1a17SAkeem G Abodunrin static void
_resize_bar(struct drm_i915_private * i915,int resno,resource_size_t size)32a91d1a17SAkeem G Abodunrin _resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size)
33a91d1a17SAkeem G Abodunrin {
34a91d1a17SAkeem G Abodunrin struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
35a91d1a17SAkeem G Abodunrin int bar_size = pci_rebar_bytes_to_size(size);
36a91d1a17SAkeem G Abodunrin int ret;
37a91d1a17SAkeem G Abodunrin
38a91d1a17SAkeem G Abodunrin _release_bars(pdev);
39a91d1a17SAkeem G Abodunrin
40a91d1a17SAkeem G Abodunrin ret = pci_resize_resource(pdev, resno, bar_size);
41a91d1a17SAkeem G Abodunrin if (ret) {
42a91d1a17SAkeem G Abodunrin drm_info(&i915->drm, "Failed to resize BAR%d to %dM (%pe)\n",
43a91d1a17SAkeem G Abodunrin resno, 1 << bar_size, ERR_PTR(ret));
44a91d1a17SAkeem G Abodunrin return;
45a91d1a17SAkeem G Abodunrin }
46a91d1a17SAkeem G Abodunrin
47a91d1a17SAkeem G Abodunrin drm_info(&i915->drm, "BAR%d resized to %dM\n", resno, 1 << bar_size);
48a91d1a17SAkeem G Abodunrin }
49a91d1a17SAkeem G Abodunrin
i915_resize_lmem_bar(struct drm_i915_private * i915,resource_size_t lmem_size)50a91d1a17SAkeem G Abodunrin static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size)
51a91d1a17SAkeem G Abodunrin {
52a91d1a17SAkeem G Abodunrin struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
53a91d1a17SAkeem G Abodunrin struct pci_bus *root = pdev->bus;
54a91d1a17SAkeem G Abodunrin struct resource *root_res;
55a91d1a17SAkeem G Abodunrin resource_size_t rebar_size;
5617cd10a4SPriyanka Dandamudi resource_size_t current_size;
571de17842SAndrzej Hajda intel_wakeref_t wakeref;
58a91d1a17SAkeem G Abodunrin u32 pci_cmd;
59a91d1a17SAkeem G Abodunrin int i;
60a91d1a17SAkeem G Abodunrin
616bba2b30SPiotr Piórkowski current_size = roundup_pow_of_two(pci_resource_len(pdev, GEN12_LMEM_BAR));
6217cd10a4SPriyanka Dandamudi
6317cd10a4SPriyanka Dandamudi if (i915->params.lmem_bar_size) {
6417cd10a4SPriyanka Dandamudi u32 bar_sizes;
6517cd10a4SPriyanka Dandamudi
6617cd10a4SPriyanka Dandamudi rebar_size = i915->params.lmem_bar_size *
6717cd10a4SPriyanka Dandamudi (resource_size_t)SZ_1M;
686bba2b30SPiotr Piórkowski bar_sizes = pci_rebar_get_possible_sizes(pdev, GEN12_LMEM_BAR);
6917cd10a4SPriyanka Dandamudi
7017cd10a4SPriyanka Dandamudi if (rebar_size == current_size)
7117cd10a4SPriyanka Dandamudi return;
7217cd10a4SPriyanka Dandamudi
7317cd10a4SPriyanka Dandamudi if (!(bar_sizes & BIT(pci_rebar_bytes_to_size(rebar_size))) ||
7417cd10a4SPriyanka Dandamudi rebar_size >= roundup_pow_of_two(lmem_size)) {
7517cd10a4SPriyanka Dandamudi rebar_size = lmem_size;
7617cd10a4SPriyanka Dandamudi
7717cd10a4SPriyanka Dandamudi drm_info(&i915->drm,
7817cd10a4SPriyanka Dandamudi "Given bar size is not within supported size, setting it to default: %llu\n",
7917cd10a4SPriyanka Dandamudi (u64)lmem_size >> 20);
8017cd10a4SPriyanka Dandamudi }
8117cd10a4SPriyanka Dandamudi } else {
8217cd10a4SPriyanka Dandamudi rebar_size = current_size;
83a91d1a17SAkeem G Abodunrin
84a91d1a17SAkeem G Abodunrin if (rebar_size != roundup_pow_of_two(lmem_size))
85a91d1a17SAkeem G Abodunrin rebar_size = lmem_size;
86a91d1a17SAkeem G Abodunrin else
87a91d1a17SAkeem G Abodunrin return;
8817cd10a4SPriyanka Dandamudi }
89a91d1a17SAkeem G Abodunrin
90a91d1a17SAkeem G Abodunrin /* Find out if root bus contains 64bit memory addressing */
91a91d1a17SAkeem G Abodunrin while (root->parent)
92a91d1a17SAkeem G Abodunrin root = root->parent;
93a91d1a17SAkeem G Abodunrin
94a91d1a17SAkeem G Abodunrin pci_bus_for_each_resource(root, root_res, i) {
95a91d1a17SAkeem G Abodunrin if (root_res && root_res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) &&
96a91d1a17SAkeem G Abodunrin root_res->start > 0x100000000ull)
97a91d1a17SAkeem G Abodunrin break;
98a91d1a17SAkeem G Abodunrin }
99a91d1a17SAkeem G Abodunrin
100a91d1a17SAkeem G Abodunrin /* pci_resize_resource will fail anyways */
101a91d1a17SAkeem G Abodunrin if (!root_res) {
102a91d1a17SAkeem G Abodunrin drm_info(&i915->drm, "Can't resize LMEM BAR - platform support is missing\n");
103a91d1a17SAkeem G Abodunrin return;
104a91d1a17SAkeem G Abodunrin }
105a91d1a17SAkeem G Abodunrin
1061de17842SAndrzej Hajda /*
1071de17842SAndrzej Hajda * Releasing forcewake during BAR resizing results in later forcewake
1081de17842SAndrzej Hajda * ack timeouts and former can happen any time - it is asynchronous.
1091de17842SAndrzej Hajda * Grabbing all forcewakes prevents it.
1101de17842SAndrzej Hajda */
1111de17842SAndrzej Hajda with_intel_runtime_pm(i915->uncore.rpm, wakeref) {
1121de17842SAndrzej Hajda intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL);
1131de17842SAndrzej Hajda
114a91d1a17SAkeem G Abodunrin /* First disable PCI memory decoding references */
115a91d1a17SAkeem G Abodunrin pci_read_config_dword(pdev, PCI_COMMAND, &pci_cmd);
116a91d1a17SAkeem G Abodunrin pci_write_config_dword(pdev, PCI_COMMAND,
117a91d1a17SAkeem G Abodunrin pci_cmd & ~PCI_COMMAND_MEMORY);
118a91d1a17SAkeem G Abodunrin
1196bba2b30SPiotr Piórkowski _resize_bar(i915, GEN12_LMEM_BAR, rebar_size);
120a91d1a17SAkeem G Abodunrin
121a91d1a17SAkeem G Abodunrin pci_assign_unassigned_bus_resources(pdev->bus);
122a91d1a17SAkeem G Abodunrin pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd);
1231de17842SAndrzej Hajda intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL);
1241de17842SAndrzej Hajda }
125a91d1a17SAkeem G Abodunrin }
1269cae5b31SNirmoy Das #else
i915_resize_lmem_bar(struct drm_i915_private * i915,resource_size_t lmem_size)1279cae5b31SNirmoy Das static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {}
1289cae5b31SNirmoy Das #endif
129a91d1a17SAkeem G Abodunrin
1308b1f7f92SThomas Hellström static int
region_lmem_release(struct intel_memory_region * mem)131f178b897SMatthew Auld region_lmem_release(struct intel_memory_region *mem)
132f178b897SMatthew Auld {
1338b1f7f92SThomas Hellström int ret;
1348b1f7f92SThomas Hellström
1358b1f7f92SThomas Hellström ret = intel_region_ttm_fini(mem);
136f178b897SMatthew Auld io_mapping_fini(&mem->iomap);
1378b1f7f92SThomas Hellström
1388b1f7f92SThomas Hellström return ret;
139f178b897SMatthew Auld }
140f178b897SMatthew Auld
141f178b897SMatthew Auld static int
region_lmem_init(struct intel_memory_region * mem)142f178b897SMatthew Auld region_lmem_init(struct intel_memory_region *mem)
143f178b897SMatthew Auld {
144f178b897SMatthew Auld int ret;
145f178b897SMatthew Auld
146f178b897SMatthew Auld if (!io_mapping_init_wc(&mem->iomap,
147f178b897SMatthew Auld mem->io_start,
148235582caSMatthew Auld mem->io_size))
1498c26491fSLucas De Marchi return -EIO;
150f178b897SMatthew Auld
151d1487389SThomas Hellström ret = intel_region_ttm_init(mem);
152f178b897SMatthew Auld if (ret)
153d1487389SThomas Hellström goto out_no_buddy;
154d1487389SThomas Hellström
155d1487389SThomas Hellström return 0;
156d1487389SThomas Hellström
157d1487389SThomas Hellström out_no_buddy:
158f178b897SMatthew Auld io_mapping_fini(&mem->iomap);
159f178b897SMatthew Auld
160f178b897SMatthew Auld return ret;
161f178b897SMatthew Auld }
162f178b897SMatthew Auld
163f178b897SMatthew Auld static const struct intel_memory_region_ops intel_region_lmem_ops = {
164f178b897SMatthew Auld .init = region_lmem_init,
165f178b897SMatthew Auld .release = region_lmem_release,
166213d5092SThomas Hellström .init_object = __i915_gem_ttm_object_init,
167f178b897SMatthew Auld };
168f178b897SMatthew Auld
get_legacy_lowmem_region(struct intel_uncore * uncore,u64 * start,u32 * size)1697c5cc941SImre Deak static bool get_legacy_lowmem_region(struct intel_uncore *uncore,
1707c5cc941SImre Deak u64 *start, u32 *size)
1717c5cc941SImre Deak {
1723c4b33d0SMatt Roper if (!IS_DG1(uncore->i915))
1737c5cc941SImre Deak return false;
1747c5cc941SImre Deak
1757c5cc941SImre Deak *start = 0;
1767c5cc941SImre Deak *size = SZ_1M;
1777c5cc941SImre Deak
1787c5cc941SImre Deak drm_dbg(&uncore->i915->drm, "LMEM: reserved legacy low-memory [0x%llx-0x%llx]\n",
1797c5cc941SImre Deak *start, *start + *size);
1807c5cc941SImre Deak
1817c5cc941SImre Deak return true;
1827c5cc941SImre Deak }
1837c5cc941SImre Deak
reserve_lowmem_region(struct intel_uncore * uncore,struct intel_memory_region * mem)1847c5cc941SImre Deak static int reserve_lowmem_region(struct intel_uncore *uncore,
1857c5cc941SImre Deak struct intel_memory_region *mem)
1867c5cc941SImre Deak {
1877c5cc941SImre Deak u64 reserve_start;
1887c5cc941SImre Deak u32 reserve_size;
1897c5cc941SImre Deak int ret;
1907c5cc941SImre Deak
1917c5cc941SImre Deak if (!get_legacy_lowmem_region(uncore, &reserve_start, &reserve_size))
1927c5cc941SImre Deak return 0;
1937c5cc941SImre Deak
1947c5cc941SImre Deak ret = intel_memory_region_reserve(mem, reserve_start, reserve_size);
1957c5cc941SImre Deak if (ret)
1967c5cc941SImre Deak drm_err(&uncore->i915->drm, "LMEM: reserving low memory region failed\n");
1977c5cc941SImre Deak
1987c5cc941SImre Deak return ret;
1997c5cc941SImre Deak }
2007c5cc941SImre Deak
setup_lmem(struct intel_gt * gt)201a50ca39fSMatthew Auld static struct intel_memory_region *setup_lmem(struct intel_gt *gt)
202a50ca39fSMatthew Auld {
203a50ca39fSMatthew Auld struct drm_i915_private *i915 = gt->i915;
2047f2aa5b3SCQ Tang struct intel_uncore *uncore = gt->uncore;
20597c463b2SThomas Zimmermann struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
206a50ca39fSMatthew Auld struct intel_memory_region *mem;
207ca921624SMatthew Auld resource_size_t min_page_size;
208a50ca39fSMatthew Auld resource_size_t io_start;
20956eda725SMatthew Auld resource_size_t io_size;
2107f2aa5b3SCQ Tang resource_size_t lmem_size;
2117c5cc941SImre Deak int err;
212a50ca39fSMatthew Auld
213a50ca39fSMatthew Auld if (!IS_DGFX(i915))
214a50ca39fSMatthew Auld return ERR_PTR(-ENODEV);
215a50ca39fSMatthew Auld
2161bba7323SPiotr Piórkowski if (!i915_pci_resource_valid(pdev, GEN12_LMEM_BAR))
2171bba7323SPiotr Piórkowski return ERR_PTR(-ENXIO);
2181bba7323SPiotr Piórkowski
2194b31b8e3SAbdiel Janulgue if (HAS_FLAT_CCS(i915)) {
2208f6de231SNirmoy Das resource_size_t lmem_range;
2214b31b8e3SAbdiel Janulgue u64 tile_stolen, flat_ccs_base;
2224b31b8e3SAbdiel Janulgue
223*306f7a5bSAndi Shyti lmem_range = intel_gt_mcr_read_any(to_gt(i915), XEHP_TILE0_ADDR_RANGE) & 0xFFFF;
2247d809707SMatt Roper lmem_size = lmem_range >> XEHP_TILE_LMEM_RANGE_SHIFT;
2258f6de231SNirmoy Das lmem_size *= SZ_1G;
2268f6de231SNirmoy Das
2277d809707SMatt Roper flat_ccs_base = intel_gt_mcr_read_any(gt, XEHP_FLAT_CCS_BASE_ADDR);
2287d809707SMatt Roper flat_ccs_base = (flat_ccs_base >> XEHP_CCS_BASE_SHIFT) * SZ_64K;
2294b31b8e3SAbdiel Janulgue
2304b31b8e3SAbdiel Janulgue if (GEM_WARN_ON(lmem_size < flat_ccs_base))
231d158367cSNirmoy Das return ERR_PTR(-EIO);
2324b31b8e3SAbdiel Janulgue
2334b31b8e3SAbdiel Janulgue tile_stolen = lmem_size - flat_ccs_base;
2344b31b8e3SAbdiel Janulgue
2354b31b8e3SAbdiel Janulgue /* If the FLAT_CCS_BASE_ADDR register is not populated, flag an error */
2364b31b8e3SAbdiel Janulgue if (tile_stolen == lmem_size)
2374b31b8e3SAbdiel Janulgue drm_err(&i915->drm,
2384b31b8e3SAbdiel Janulgue "CCS_BASE_ADDR register did not have expected value\n");
2394b31b8e3SAbdiel Janulgue
2404b31b8e3SAbdiel Janulgue lmem_size -= tile_stolen;
2414b31b8e3SAbdiel Janulgue } else {
2424b31b8e3SAbdiel Janulgue /* Stolen starts from GSMBASE without CCS */
2434b31b8e3SAbdiel Janulgue lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE);
2444b31b8e3SAbdiel Janulgue }
2454b31b8e3SAbdiel Janulgue
246a91d1a17SAkeem G Abodunrin i915_resize_lmem_bar(i915, lmem_size);
247a91d1a17SAkeem G Abodunrin
248be658e70SCQ Tang if (i915->params.lmem_size > 0) {
249be658e70SCQ Tang lmem_size = min_t(resource_size_t, lmem_size,
250be658e70SCQ Tang mul_u32_u32(i915->params.lmem_size, SZ_1M));
251be658e70SCQ Tang }
2527f2aa5b3SCQ Tang
2536bba2b30SPiotr Piórkowski io_start = pci_resource_start(pdev, GEN12_LMEM_BAR);
2546bba2b30SPiotr Piórkowski io_size = min(pci_resource_len(pdev, GEN12_LMEM_BAR), lmem_size);
25556eda725SMatthew Auld if (!io_size)
256d158367cSNirmoy Das return ERR_PTR(-EIO);
257a50ca39fSMatthew Auld
258ca921624SMatthew Auld min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K :
259ca921624SMatthew Auld I915_GTT_PAGE_SIZE_4K;
260a50ca39fSMatthew Auld mem = intel_memory_region_create(i915,
261a50ca39fSMatthew Auld 0,
2627f2aa5b3SCQ Tang lmem_size,
263ca921624SMatthew Auld min_page_size,
264a50ca39fSMatthew Auld io_start,
26556eda725SMatthew Auld io_size,
266d1487389SThomas Hellström INTEL_MEMORY_LOCAL,
267d1487389SThomas Hellström 0,
268a50ca39fSMatthew Auld &intel_region_lmem_ops);
269a50ca39fSMatthew Auld if (IS_ERR(mem))
270a50ca39fSMatthew Auld return mem;
271a50ca39fSMatthew Auld
2727c5cc941SImre Deak err = reserve_lowmem_region(uncore, mem);
2737c5cc941SImre Deak if (err)
2747c5cc941SImre Deak goto err_region_put;
2757c5cc941SImre Deak
276a50ca39fSMatthew Auld drm_dbg(&i915->drm, "Local memory: %pR\n", &mem->region);
277a50ca39fSMatthew Auld drm_dbg(&i915->drm, "Local memory IO start: %pa\n",
278a50ca39fSMatthew Auld &mem->io_start);
279235582caSMatthew Auld drm_info(&i915->drm, "Local memory IO size: %pa\n",
280235582caSMatthew Auld &mem->io_size);
2817f2aa5b3SCQ Tang drm_info(&i915->drm, "Local memory available: %pa\n",
2827f2aa5b3SCQ Tang &lmem_size);
283a50ca39fSMatthew Auld
284eb1c535fSMatthew Auld if (io_size < lmem_size)
285eb1c535fSMatthew Auld drm_info(&i915->drm, "Using a reduced BAR size of %lluMiB. Consider enabling 'Resizable BAR' or similar, if available in the BIOS.\n",
286eb1c535fSMatthew Auld (u64)io_size >> 20);
287eb1c535fSMatthew Auld
288a50ca39fSMatthew Auld return mem;
2897c5cc941SImre Deak
2907c5cc941SImre Deak err_region_put:
2918b1f7f92SThomas Hellström intel_memory_region_destroy(mem);
2927c5cc941SImre Deak return ERR_PTR(err);
293a50ca39fSMatthew Auld }
294a50ca39fSMatthew Auld
intel_gt_setup_lmem(struct intel_gt * gt)295a50ca39fSMatthew Auld struct intel_memory_region *intel_gt_setup_lmem(struct intel_gt *gt)
296a50ca39fSMatthew Auld {
297a50ca39fSMatthew Auld return setup_lmem(gt);
298a50ca39fSMatthew Auld }
299