git: f1f58bdf7b5f - main - acpi_pci: Honor device proximity for DMA tags
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 27 Aug 2026 22:53:03 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=f1f58bdf7b5fc58e6011c6ac2ae2ba129dc41991
commit f1f58bdf7b5fc58e6011c6ac2ae2ba129dc41991
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-27 06:23:42 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-27 22:51:10 +0000
acpi_pci: Honor device proximity for DMA tags
A PCI function with its own _PXM still inherits a DMA tag carrying
the upstream bridge's proximity domain. Resolving an SR-IOV VF's
locality through its PF therefore does not affect the domain used for
DMA allocations.
Create and cache a private child tag when the function, or a VF's
owning PF, has an explicit _PXM. Parent it to the existing PCI or IOMMU
tag so its constraints remain intact, then apply the function's domain
without mutating a shared tag.
pci_get_dma_tag() already performs the IOMMU lookup, so remove the
duplicated lookup in the ACPI subclass while here.
Reviewed by: jhb
MFC after: 2 weeks
Sponsored by: BBOX.io
Differential Revision: https://reviews.freebsd.org/D59063
---
sys/dev/acpica/acpi_pci.c | 58 ++++++++++++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 21 deletions(-)
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index 1f04de54ac44..347a68e17e53 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -28,7 +28,6 @@
#include <sys/cdefs.h>
#include "opt_acpi.h"
-#include "opt_iommu.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -51,8 +50,6 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pci_private.h>
-#include <dev/iommu/iommu.h>
-
/* Hooks for the ACPI CA debugging infrastructure. */
#define _COMPONENT ACPI_BUS
ACPI_MODULE_NAME("PCI")
@@ -60,6 +57,7 @@ ACPI_MODULE_NAME("PCI")
struct acpi_pci_devinfo {
struct pci_devinfo ap_dinfo;
ACPI_HANDLE ap_handle;
+ bus_dma_tag_t ap_dma_tag;
int ap_flags;
int ap_domain;
};
@@ -179,6 +177,8 @@ acpi_pci_child_deleted(device_t dev, device_t child)
{
struct acpi_pci_devinfo *dinfo = device_get_ivars(child);
+ if (dinfo->ap_dma_tag != NULL)
+ bus_dma_tag_destroy(dinfo->ap_dma_tag);
if (acpi_get_device(dinfo->ap_handle) == child)
AcpiDetachData(dinfo->ap_handle, acpi_fake_objhandler);
pci_child_deleted(dev, child);
@@ -560,26 +560,42 @@ acpi_pci_detach(device_t dev)
return (pci_detach(dev));
}
-#ifdef IOMMU
-static bus_dma_tag_t
-acpi_pci_get_dma_tag(device_t bus, device_t child)
-{
- bus_dma_tag_t tag;
-
- if (device_get_parent(child) == bus) {
- /* try iommu and return if it works */
- tag = iommu_get_dma_tag(bus, child);
- } else
- tag = NULL;
- if (tag == NULL)
- tag = pci_get_dma_tag(bus, child);
- return (tag);
-}
-#else
static bus_dma_tag_t
acpi_pci_get_dma_tag(device_t bus, device_t child)
{
+ struct acpi_pci_devinfo *dinfo;
+ bus_dma_tag_t parent, tag;
+ int domain, error;
- return (pci_get_dma_tag(bus, child));
+ if (device_get_parent(child) != bus)
+ return (pci_get_dma_tag(bus, child));
+ dinfo = device_get_ivars(child);
+ if (dinfo->ap_dma_tag != NULL)
+ return (dinfo->ap_dma_tag);
+
+ /*
+ * The parent tag already carries the upstream bridge's proximity
+ * domain. Only create a private tag when this function (or its PF,
+ * for a VF) supplies a more specific _PXM. In particular, do not
+ * change the shared PCI or IOMMU tag in place.
+ */
+ domain = acpi_pci_get_locality_domain(child);
+ if (domain < 0)
+ return (pci_get_dma_tag(bus, child));
+
+ parent = pci_get_dma_tag(bus, child);
+ if (parent == NULL)
+ return (NULL);
+ error = bus_dma_tag_create(parent, 1, 0, BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE,
+ BUS_SPACE_UNRESTRICTED, BUS_SPACE_MAXSIZE, 0, NULL, NULL, &tag);
+ if (error != 0)
+ return (parent);
+ error = bus_dma_tag_set_domain(tag, domain);
+ if (error != 0) {
+ bus_dma_tag_destroy(tag);
+ return (parent);
+ }
+ dinfo->ap_dma_tag = tag;
+ return (tag);
}
-#endif