Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Apr 2025 10:00:57 GMT
From:      =?utf-8?Q?Jean-S=C3=A9bastien?= =?utf-8?Q?P=C3=A9dron?= <dumbbell@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 21b556557e46 - main - linuxkpi: Fix `pci_upstream_bridge()` with DRM devices
Message-ID:  <202504131000.53DA0vEZ083996@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <dumbbell@FreeBSD.org>
AuthorDate: 2025-03-03 23:48:20 +0000
Commit:     Jean-Sébastien Pédron <dumbbell@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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202504131000.53DA0vEZ083996>