[PATCH 7/8] amdgpu: implement a BAR size quirks list

Darren Salt devspam at moreofthesa.me.uk
Sun Dec 13 22:53:22 UTC 2020


Intended for devices which are misreporting available/supported BAR sizes.

This may be insufficient to identify some devices. The inclusion of the
reported BAR sizes bitmap is to assist with identification.
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 43 ++++++++++++++++++++--
 1 file changed, 39 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 0f05a75be34e..442eca5fc6a4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -897,6 +897,34 @@ void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
 		__clear_bit(wb, adev->wb.used);
 }
 
+static const struct amdgpu_rebar_quirk {
+	u32 chip_vendor, chip_device;
+	u32 subsys_vendor, subsys_device;
+	int reported_sizes;	/* 0, or as reported by pci_rebar_get_possible_sizes */
+	int available_sizes;	/* bitmap (-256 for anything >= 256MB, effectively automatic) */
+} amdgpu_rebar_quirk_list[] = {
+	{ 0, 0, 0, 0, 0, 0 }
+};
+
+static int amdgpu_rebar_quirk_check(struct amdgpu_device *adev, int reported_sizes)
+{
+	const struct pci_dev *pdev = adev->pdev;
+	const struct amdgpu_rebar_quirk *p = amdgpu_rebar_quirk_list;
+
+	while (p && p->chip_device != 0) {
+		if (pdev->vendor == p->chip_vendor &&
+		    pdev->device == p->chip_device &&
+		    pdev->subsystem_vendor == p->subsys_vendor &&
+		    pdev->subsystem_device == p->subsys_device &&
+		    (!reported_sizes || !p->available_sizes || reported_sizes == p->reported_sizes)) {
+			dev_info(adev->dev, "quirk: overriding BAR possible sizes list.");
+			return p->available_sizes;
+		}
+		++p;
+	}
+	return 0;
+}
+
 /**
  * amdgpu_device_resize_fb_bar - try to resize FB BAR
  *
@@ -918,6 +946,7 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
 	u16 cmd;
 	int r;
 	bool nospc = false;
+	bool override_bar_sizes = amdgpu_override_bar_sizes;
 
 	/* Bypass for VF */
 	if (amdgpu_sriov_vf(adev))
@@ -954,10 +983,16 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
 	if (!res)
 		return 0;
 
-	if (amdgpu_override_bar_sizes)
+	if (override_bar_sizes)
 		available_sizes = ~(-1 << rbar_size) & ~0xFF;
-	else
-		available_sizes = pci_rebar_get_possible_sizes(adev->pdev, 0);
+	else {
+		int q = amdgpu_rebar_quirk_check(adev, available_sizes);
+		if (q)
+			override_bar_sizes = true;
+		else
+			q = pci_rebar_get_possible_sizes(adev->pdev, 0);
+		available_sizes = q;
+	}
 
 	if (max_size >= 0) {
 		/* Cause larger sizes to be ignored unless that would leave
@@ -999,7 +1034,7 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
 	     rbar_size >= 0;
 	     rbar_size = fls(available_sizes & ~(-1 << rbar_size)) - 1
 	    ) {
-		r = pci_resize_resource(adev->pdev, 0, rbar_size, amdgpu_override_bar_sizes);
+		r = pci_resize_resource(adev->pdev, 0, rbar_size, override_bar_sizes);
 		if (r == 0) {
 			break;
 		} else if (r == -ENOTSUPP) {
-- 
2.20.1



More information about the amd-gfx mailing list