Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
--- nv-pci.c 2022-01-08 23:12:19.137095516 +0000
+++ /usr/src/nvidia-495.46/nvidia/nv-pci.c 2022-01-09 00:05:21.323360921 +0000
@@ -217,7 +217,78 @@
+#define NV_GPU_BAR1 1
+static int nv_resize_pcie_bars(struct pci_dev *pci_dev) {
+ struct pci_host_bridge *host;
+ u16 cmd;
+ int r, old_size, requested_size;
+ int ret = 0;
+
+ // Check if BAR1 has PCIe rebar capabilities
+ u32 sizes = pci_rebar_get_possible_sizes(pci_dev, NV_GPU_BAR1);
+ if (sizes == 0) {
+ /* ReBAR not available. Nothing to do. */
+ return 0;
+ }
+
+ /* Try to resize the BAR to the largest supported size */
+ requested_size = fls(sizes) - 1;
+
+ /* If the kernel will refuse us, don't even try to resize,
+ but give an informative error */
+ host = pci_find_host_bridge(pci_dev->bus);
+ if (host->preserve_config) {
+ nv_printf(NV_DBG_INFO, "NVRM: Not resizing BAR because the firmware forbids moving windows.\n");
+ return 0;
+ }
+
+ nv_printf(NV_DBG_INFO, "NVRM: %04x:%02x:%02x.%x: Attempting to resize BAR1.\n",
+ NV_PCI_DOMAIN_NUMBER(pci_dev), NV_PCI_BUS_NUMBER(pci_dev),
+ NV_PCI_SLOT_NUMBER(pci_dev), PCI_FUNC(pci_dev->devfn));
+
+ /* Disable memory decoding - required by the kernel APIs */
+ pci_read_config_word(pci_dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(pci_dev, PCI_COMMAND, cmd & ~PCI_COMMAND_MEMORY);
+
+ /* Release BAR1 */
+ pci_release_resource(pci_dev, NV_GPU_BAR1);
+
+ /* Save the current size, just in case things go wrong */
+ old_size = fls(pci_resource_len(pci_dev, NV_GPU_BAR1)) >> 20;
+
+resize:
+ /* Attempt to resize BAR1 to the largest supported size */
+ r = pci_resize_resource(pci_dev, NV_GPU_BAR1, requested_size);
+
+ if (r) {
+ if (r == -ENOSPC)
+ nv_printf(NV_DBG_ERRORS, "NVRM: No address space to allocate resized BAR1.\n");
+ else if (r)
+ nv_printf(NV_DBG_ERRORS, "NVRM: BAR resizing failed with error `%d`.\n", r);
+
+ /* Re-attempt assignment of PCIe resources */
+ pci_assign_unassigned_bus_resources(pci_dev->bus);
+ }
+ if (pci_resource_flags(pci_dev, NV_GPU_BAR1) & IORESOURCE_UNSET) {
+ if (requested_size != old_size) {
+ /* Try to get the BAR back with the original size */
+ requested_size = old_size;
+ goto resize;
+ }
+ /* Something went horribly wrong and the kernel didn't manage to re-allocate BAR1.
+ This is unlikely (because we had space before), but can happen. */
+ nv_printf(NV_DBG_ERRORS, "NVRM: FATAL: Failed to re-allocate BAR1.\n");
+ ret = -ENODEV;
+ goto done;
+ }
+
+done:
+ /* Re-enable memory decoding */
+ pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
+
+ return ret;
+}
/* find nvidia devices and set initial state */
static int
@@ -428,6 +499,11 @@
goto failed;
}
+ if (!nv_resize_pcie_bars(pci_dev)) {
+ nv_printf(NV_DBG_ERRORS,
+ "NVRM: Fatal Error while attempting to resize PCIe BARs.\n");
+ }
+
NV_KMALLOC(nvl, sizeof(nv_linux_state_t));
if (nvl == NULL)
{
@@ -470,6 +546,7 @@
nvl->gpu_wakeup_callback_needed = NV_TRUE;
INIT_LIST_HEAD(&nvl->open_files);
+
for (i = 0, j = 0; i < NVRM_PCICFG_NUM_BARS && j < NV_GPU_NUM_BARS; i++)
{
if ((NV_PCI_RESOURCE_VALID(pci_dev, i)) &&
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment