This repository has been archived by the owner on May 31, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
495.46-pcie-rebar.patch
99 lines (93 loc) · 3.33 KB
/
495.46-pcie-rebar.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
--- nv-pci.c 2022-01-08 23:12:19.137095516 +0000
+++ /usr/src/nvidia-495.46/nvidia/nv-pci.c 2022-01-09 02:49:25.500844951 +0000
@@ -217,7 +217,83 @@
+#define NV_GPU_BAR1 1
+#define NV_GPU_BAR3 3
+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);
+
+ /* Release BAR3 - we don't want to resize it, it's in the same bridge, so we'll want to move it */
+ pci_release_resource(pci_dev, NV_GPU_BAR3);
+
+ /* Save the current size, just in case things go wrong */
+ old_size = pci_rebar_bytes_to_size(pci_resource_len(pci_dev, NV_GPU_BAR1));
+
+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) ||
+ (pci_resource_flags(pci_dev, NV_GPU_BAR3) & 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 +504,12 @@
goto failed;
}
+ if (nv_resize_pcie_bars(pci_dev)) {
+ nv_printf(NV_DBG_ERRORS,
+ "NVRM: Fatal Error while attempting to resize PCIe BARs.\n");
+ goto failed;
+ }
+
NV_KMALLOC(nvl, sizeof(nv_linux_state_t));
if (nvl == NULL)
{