ACPI: LoongArch: Add support for acpi_iommu_configure_id()

acpi_iommu_configure_id() currently only supports IORT and VIOT. Add
support for LoongArch's IOVT as well.

Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
Bibo Mao 2026-10-27 22:51:12 +08:00 committed by Huacai Chen
parent a9b0c34507
commit 33e3401608
3 changed files with 63 additions and 0 deletions

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/acpi.h>
#include <linux/acpi_iovt.h>
#include <linux/pci.h>
#include "init.h"
@ -209,3 +210,49 @@ void __init acpi_iovt_late_init(void)
iovt_init_devices(hdr);
acpi_put_table(hdr);
}
static int iovt_pci_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)
{
struct iovt_fwnode *np;
struct iovt_device_entry *entry;
struct device *aliased_dev = data;
u32 domain = pci_domain_nr(pdev->bus);
list_for_each_entry(np, &iovt_fwnode_list, list) {
if (domain != np->segment)
continue;
/* We're not translating ourself */
if (dev_id == np->devid)
return -EINVAL;
if (np->flag & ACPI_IOVT_IOMMU_MAGAGE_BY_SEGMENT)
goto found;
list_for_each_entry(entry, &np->ep_list, list) {
if (dev_id >= entry->start_devid && dev_id <= entry->end_devid)
goto found;
}
}
return -ENODEV;
found:
return acpi_iommu_fwspec_init(aliased_dev, (domain << 16) + dev_id, np->fwnode);
}
/*
* iovt_iommu_configure_id - Set-up IOMMU configuration for a device.
*
* @dev: device to configure
* @id_in: optional input id const value pointer
*
* Returns: 0 on success, <0 on failure
*/
int iovt_iommu_configure_id(struct device *dev, const u32 *id_in)
{
if (!dev_is_pci(dev))
return -ENODEV;
return pci_for_each_dma_alias(to_pci_dev(dev), iovt_pci_iommu_init, dev);
}

View File

@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/acpi_iort.h>
#include <linux/acpi_iovt.h>
#include <linux/acpi_rimt.h>
#include <linux/acpi_viot.h>
#include <linux/iommu.h>
@ -1625,6 +1626,8 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
err = iort_iommu_configure_id(dev, id_in);
if (err && err != -EPROBE_DEFER)
err = rimt_iommu_configure_id(dev, id_in);
if (err && err != -EPROBE_DEFER)
err = iovt_iommu_configure_id(dev, id_in);
if (err && err != -EPROBE_DEFER)
err = viot_iommu_configure(dev);

13
include/linux/acpi_iovt.h Normal file
View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ACPI_IOVT_H__
#define __ACPI_IOVT_H__
#ifdef CONFIG_ACPI_IOVT
int iovt_iommu_configure_id(struct device *dev, const u32 *id_in);
#else
static inline int iovt_iommu_configure_id(struct device *dev, const u32 *id_in)
{ return -ENODEV; }
#endif
#endif /* __ACPI_IOVT_H__ */