git: 21b556557e46 - main - linuxkpi: Fix `pci_upstream_bridge()` with DRM devices
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 13 Apr 2025 10:00:57 UTC
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);