[PATCH 3/8] ACPI: LoongArch: Enable pci acs function if acpi iovt tables exist
Bibo Mao <[email protected]> Wed, 17 Jun 2026 15:48:24 +0800
| Newsgroups | dev.linux.lists.acpica-devel,dev.linux.lists.loongarch,org.kernel.vger.linux-acpi,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
IOMMU requires pci acs function enabled, so that all the DMA transaction of pci device is routed to upper PCI bridge and IOMMU device. Here scan IOMMU iovt table in function acpi_iovt_init(), which is executed before PCI device sanning, and enable pci acs function if iovt tables exist. Signed-off-by: Bibo Mao <[email protected]> --- drivers/acpi/loongarch/iovt.c | 47 +++++++++++++++++++++++++++++++++++ include/acpi/actbl2.h | 3 +++ 2 files changed, 50 insertions(+) diff --git a/drivers/acpi/loongarch/iovt.c b/drivers/acpi/loongarch/iovt.c index 793ed13a2cef..5e3d866796a9 100644 --- a/drivers/acpi/loongarch/iovt.c +++ b/drivers/acpi/loongarch/iovt.c @@ -1,7 +1,54 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/acpi.h> +#include <linux/pci.h> #include "init.h" +#ifdef CONFIG_PCI +static void __init iovt_enable_acs(struct acpi_iovt_iommu *iommu) +{ + static bool acs_enabled __initdata; + + if (acs_enabled) + return; + + /* IOMMU V1 only supports PCI device management */ + if ((iommu->header.type == ACPI_IOVT_IOMMU_V1) || + (iommu->flags & (ACPI_IOVT_PCI_DEVICE | ACPI_IOVT_MAGAGE_BY_SEGMENT))) { + pci_request_acs(); + acs_enabled = true; + } +} +#else +static inline void iovt_enable_acs(struct acpi_iovt_iommu *iommu) { } +#endif + void __init acpi_iovt_init(void) { + acpi_status status; + struct acpi_table_header *hdr; + struct acpi_table_iovt *iovt; + struct acpi_iovt_iommu *iommu; + int i; + + status = acpi_get_table(ACPI_SIG_IOVT, 0, &hdr); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + const char *msg = acpi_format_exception(status); + + pr_err("Failed to get table, %s\n", msg); + } + + return; + } + + iovt = (struct acpi_table_iovt *)&hdr; + iommu = ACPI_ADD_PTR(struct acpi_iovt_iommu, iovt, iovt->iommu_offset); + for (i = 0; i < iovt->iommu_count; i++) { + iovt_enable_acs(iommu); + + iommu = ACPI_ADD_PTR(struct acpi_iovt_iommu, iommu, iommu->header.length); + } + + acpi_put_table(hdr); } diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index baef525367b5..acc51a42c3ed 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -892,6 +892,9 @@ struct acpi_iovt_header { /* Values for Type field above */ +#define ACPI_IOVT_PCI_DEVICE BIT(0) +#define ACPI_IOVT_PXM_VALID BIT(1) +#define ACPI_IOVT_MAGAGE_BY_SEGMENT BIT(2) enum acpi_iovt_iommu_type { ACPI_IOVT_IOMMU_V1 = 0x00, ACPI_IOVT_IOMMU_RESERVED = 0x01 /* 1 and greater are reserved */ -- 2.39.3