[PATCH 3/8] amdgpu: resize BAR0 to the maximum available size, even if it doesn't cover VRAM (v5)
Darren Salt
devspam at moreofthesa.me.uk
Tue Dec 15 01:08:57 UTC 2020
This allows BAR0 resizing to be done for cards which don't advertise support
for a size large enough to cover the VRAM but which do advertise at least
one size larger than the default. For example, my RX 5600 XT, which
advertises 256MB, 512MB and 1GB.
[v5] Drop the retry loop…
[v4] Use bit ops to find sizes to try.
[v3] Don't use pci_rebar_get_current_size().
[v2] Rewritten to use PCI helper functions; some extra log text.
Signed-off-by: Darren Salt <devspam at moreofthesa.me.uk>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 38 +++++++++++++++++-----
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 6637b84aeb85..ac94f8db06a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1106,8 +1106,9 @@ void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
*/
int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
{
- u64 space_needed = roundup_pow_of_two(adev->gmc.real_vram_size);
- u32 rbar_size = order_base_2(((space_needed >> 20) | 1)) - 1;
+ int rbar_size, current_size;
+ u64 current_bytes;
+ u32 available_sizes;
struct pci_bus *root;
struct resource *res;
unsigned i;
@@ -1118,11 +1119,15 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
if (amdgpu_sriov_vf(adev))
return 0;
- /* skip if the bios has already enabled large BAR */
- if (adev->gmc.real_vram_size &&
- (pci_resource_len(adev->pdev, 0) >= adev->gmc.real_vram_size))
+ current_bytes = pci_resource_len(adev->pdev, 0);
+
+ /* Skip if the BIOS has already enabled large BAR, covering the VRAM */
+ if (current_bytes >= adev->gmc.real_vram_size)
return 0;
+ current_size = current_bytes ? pci_rebar_bytes_to_size(current_bytes) : -1;
+ rbar_size = pci_rebar_bytes_to_size(adev->gmc.real_vram_size);
+
/* Check if the root BUS has 64bit memory resources */
root = adev->pdev->bus;
while (root->parent)
@@ -1138,6 +1143,18 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
if (!res)
return 0;
+ available_sizes = pci_rebar_get_possible_sizes(adev->pdev, 0);
+ if (available_sizes == 0)
+ return 0;
+
+ /* Find the bit pos representing the smallest size covering the VRAM.
+ * Otherwise find the bit pos representing the largest available size.
+ * rbar_size may be smaller but should be unchanged.
+ */
+ rbar_size = (ffs(available_sizes & (-1 << rbar_size)) ? : fls(available_sizes)) - 1;
+ if (rbar_size < 0)
+ return 0; /* can't happen */
+
/* Disable memory decoding while we change the BAR addresses and size */
pci_read_config_word(adev->pdev, PCI_COMMAND, &cmd);
pci_write_config_word(adev->pdev, PCI_COMMAND,
@@ -1151,10 +1168,13 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
pci_release_resource(adev->pdev, 0);
r = pci_resize_resource(adev->pdev, 0, rbar_size);
- if (r == -ENOSPC)
- DRM_INFO("Not enough PCI address space for a large BAR.");
- else if (r && r != -ENOTSUPP)
- DRM_ERROR("Problem resizing BAR0 (%d).", r);
+ if (r == -ENOTSUPP) {
+ dev_info(adev->dev, "BAR resizing not supported.");
+ } else if (r == -ENOSPC) {
+ dev_info(adev->dev, "Not enough PCI address space for a large BAR.");
+ } else if (r) {
+ dev_err(adev->dev, "Problem resizing BAR0 (%d).", r);
+ }
pci_assign_unassigned_bus_resources(adev->pdev->bus);
--
2.20.1
More information about the amd-gfx
mailing list