The branch main has been updated by dumbbell:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=21b556557e464701960c4a8b4dcc062cb3954ddc

commit 21b556557e464701960c4a8b4dcc062cb3954ddc
Author:     Jean-Sébastien Pédron <dumbb...@freebsd.org>
AuthorDate: 2025-03-03 23:48:20 +0000
Commit:     Jean-Sébastien Pédron <dumbb...@freebsd.org>
CommitDate: 2025-04-13 09:51:13 +0000

    linuxkpi: Fix `pci_upstream_bridge()` with DRM devices
    
    In the case of DRM drivers, the passed device is a child of `vgapci`. We
    want to start the lookup from `vgapci`, so the parent of the passed
    `drmn`. We use the `isdrm` flag to determine if we are in this
    situation.
    
    This fixes an infinite loop with the amdgpu DRM driver that started to
    use this function in Linux 6.8: `pci_upstream_bridge()` was returning
    itself and the code in amdgpu was calling it again, hoping to get a
    device with a vendor that is not "ATI".
    
    Reviewed by:    bz
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D49388
---
 sys/compat/linuxkpi/common/include/linux/pci.h | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h 
b/sys/compat/linuxkpi/common/include/linux/pci.h
index afd6c827b3b4..e4e8e5c0abd1 100644
--- a/sys/compat/linuxkpi/common/include/linux/pci.h
+++ b/sys/compat/linuxkpi/common/include/linux/pci.h
@@ -523,7 +523,20 @@ pci_upstream_bridge(struct pci_dev *pdev)
        if (pdev == pdev->bus->self) {
                device_t bridge;
 
-               bridge = device_get_parent(pdev->dev.bsddev);
+               /*
+                * In the case of DRM drivers, the passed device is a child of
+                * `vgapci`. We want to start the lookup from `vgapci`, so the
+                * parent of the passed `drmn`.
+                *
+                * We can use the `isdrm` flag to determine this.
+                */
+               bridge = pdev->dev.bsddev;
+               if (pdev->pdrv != NULL && pdev->pdrv->isdrm)
+                       bridge = device_get_parent(bridge);
+               if (bridge == NULL)
+                       goto done;
+
+               bridge = device_get_parent(bridge);
                if (bridge == NULL)
                        goto done;
                bridge = device_get_parent(bridge);

Reply via email to