1382876afSLucas De Marchi // SPDX-License-Identifier: MIT 2382876afSLucas De Marchi /* 3382876afSLucas De Marchi * Copyright © 2025 Intel Corporation 4382876afSLucas De Marchi */ 5382876afSLucas De Marchi 6382876afSLucas De Marchi #include <linux/pci.h> 7382876afSLucas De Marchi #include <linux/types.h> 8382876afSLucas De Marchi 9382876afSLucas De Marchi #include "regs/xe_bars.h" 10382876afSLucas De Marchi #include "xe_device_types.h" 11382876afSLucas De Marchi #include "xe_module.h" 12382876afSLucas De Marchi #include "xe_pci_rebar.h" 13*0b075f82SLucas De Marchi #include "xe_printk.h" 14382876afSLucas De Marchi 15382876afSLucas De Marchi static void resize_bar(struct xe_device *xe, int resno, resource_size_t size) 16382876afSLucas De Marchi { 17382876afSLucas De Marchi struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 18382876afSLucas De Marchi int bar_size = pci_rebar_bytes_to_size(size); 19382876afSLucas De Marchi int ret; 20382876afSLucas De Marchi 21382876afSLucas De Marchi ret = pci_resize_resource(pdev, resno, bar_size, 0); 22382876afSLucas De Marchi if (ret) { 23*0b075f82SLucas De Marchi xe_info(xe, "Failed to resize BAR%d to %dMiB (%pe). Consider enabling 'Resizable BAR' support in your BIOS\n", 24382876afSLucas De Marchi resno, 1 << bar_size, ERR_PTR(ret)); 25382876afSLucas De Marchi return; 26382876afSLucas De Marchi } 27382876afSLucas De Marchi 28*0b075f82SLucas De Marchi xe_info(xe, "BAR%d resized to %dMiB\n", resno, 1 << bar_size); 29382876afSLucas De Marchi } 30382876afSLucas De Marchi 31382876afSLucas De Marchi /* 32382876afSLucas De Marchi * xe_pci_rebar_resize - Resize the LMEMBAR 33382876afSLucas De Marchi * @xe: xe device instance 34382876afSLucas De Marchi * 35382876afSLucas De Marchi * If vram_bar_size module param is set, attempt to set to the requested size 36382876afSLucas De Marchi * else set to maximum possible size. 37382876afSLucas De Marchi */ 38382876afSLucas De Marchi void xe_pci_rebar_resize(struct xe_device *xe) 39382876afSLucas De Marchi { 40382876afSLucas De Marchi int force_vram_bar_size = xe_modparam.force_vram_bar_size; 41382876afSLucas De Marchi struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 42382876afSLucas De Marchi struct pci_bus *root = pdev->bus; 43382876afSLucas De Marchi resource_size_t current_size; 44382876afSLucas De Marchi resource_size_t rebar_size; 45382876afSLucas De Marchi struct resource *root_res; 46382876afSLucas De Marchi int max_size, i; 47382876afSLucas De Marchi u32 pci_cmd; 48382876afSLucas De Marchi 49382876afSLucas De Marchi /* gather some relevant info */ 50382876afSLucas De Marchi current_size = pci_resource_len(pdev, LMEM_BAR); 51382876afSLucas De Marchi 52382876afSLucas De Marchi if (force_vram_bar_size < 0) 53382876afSLucas De Marchi return; 54382876afSLucas De Marchi 55382876afSLucas De Marchi /* set to a specific size? */ 56382876afSLucas De Marchi if (force_vram_bar_size) { 57382876afSLucas De Marchi rebar_size = pci_rebar_bytes_to_size(force_vram_bar_size * 58382876afSLucas De Marchi (resource_size_t)SZ_1M); 59382876afSLucas De Marchi 60382876afSLucas De Marchi if (!pci_rebar_size_supported(pdev, LMEM_BAR, rebar_size)) { 61*0b075f82SLucas De Marchi xe_info(xe, "Requested size %lluMiB is not supported by rebar sizes: 0x%llx. Leaving default: %lluMiB\n", 62*0b075f82SLucas De Marchi (u64)pci_rebar_size_to_bytes(rebar_size) >> ilog2(SZ_1M), 63382876afSLucas De Marchi pci_rebar_get_possible_sizes(pdev, LMEM_BAR), 64*0b075f82SLucas De Marchi (u64)current_size >> ilog2(SZ_1M)); 65382876afSLucas De Marchi return; 66382876afSLucas De Marchi } 67382876afSLucas De Marchi 68382876afSLucas De Marchi rebar_size = pci_rebar_size_to_bytes(rebar_size); 69382876afSLucas De Marchi if (rebar_size == current_size) 70382876afSLucas De Marchi return; 71382876afSLucas De Marchi } else { 72382876afSLucas De Marchi max_size = pci_rebar_get_max_size(pdev, LMEM_BAR); 73382876afSLucas De Marchi if (max_size < 0) 74382876afSLucas De Marchi return; 75382876afSLucas De Marchi rebar_size = pci_rebar_size_to_bytes(max_size); 76382876afSLucas De Marchi 77382876afSLucas De Marchi /* only resize if larger than current */ 78382876afSLucas De Marchi if (rebar_size <= current_size) 79382876afSLucas De Marchi return; 80382876afSLucas De Marchi } 81382876afSLucas De Marchi 82*0b075f82SLucas De Marchi xe_info(xe, "Attempting to resize bar from %lluMiB -> %lluMiB\n", 83*0b075f82SLucas De Marchi (u64)current_size >> ilog2(SZ_1M), (u64)rebar_size >> ilog2(SZ_1M)); 84382876afSLucas De Marchi 85382876afSLucas De Marchi while (root->parent) 86382876afSLucas De Marchi root = root->parent; 87382876afSLucas De Marchi 88382876afSLucas De Marchi pci_bus_for_each_resource(root, root_res, i) { 89382876afSLucas De Marchi if (root_res && root_res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) && 90382876afSLucas De Marchi (u64)root_res->start > 0x100000000ul) 91382876afSLucas De Marchi break; 92382876afSLucas De Marchi } 93382876afSLucas De Marchi 94382876afSLucas De Marchi if (!root_res) { 95*0b075f82SLucas De Marchi xe_info(xe, "Can't resize VRAM BAR - platform support is missing. Consider enabling 'Resizable BAR' support in your BIOS\n"); 96382876afSLucas De Marchi return; 97382876afSLucas De Marchi } 98382876afSLucas De Marchi 99382876afSLucas De Marchi pci_read_config_dword(pdev, PCI_COMMAND, &pci_cmd); 100382876afSLucas De Marchi pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd & ~PCI_COMMAND_MEMORY); 101382876afSLucas De Marchi 102382876afSLucas De Marchi resize_bar(xe, LMEM_BAR, rebar_size); 103382876afSLucas De Marchi 104382876afSLucas De Marchi pci_assign_unassigned_bus_resources(pdev->bus); 105382876afSLucas De Marchi pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd); 106382876afSLucas De Marchi } 107