// SPDX-License-Identifier: GPL-2.0 /* * Virtual I/O topology * * The Virtual I/O Translation Table (VIOT) describes the topology of * para-virtual IOMMUs and the endpoints they manage. The OS uses it to * initialize devices in the right order, preventing endpoints from issuing DMA * before their IOMMU is ready. * * When binding a driver to a device, before calling the device driver's probe() * method, the driver infrastructure calls dma_configure(). At that point the * VIOT driver looks for an IOMMU associated to the device in the VIOT table. * If an IOMMU exists and has been initialized, the VIOT driver initializes the * device's IOMMU fwspec, allowing the DMA infrastructure to invoke the IOMMU * ops when the device driver configures DMA mappings. If an IOMMU exists and * hasn't yet been initialized, VIOT returns -EPROBE_DEFER to postpone probing * the device until the IOMMU is available. */ #define pr_fmt(fmt) … #include <linux/acpi_viot.h> #include <linux/fwnode.h> #include <linux/iommu.h> #include <linux/list.h> #include <linux/pci.h> #include <linux/platform_device.h> struct viot_iommu { … }; struct viot_endpoint { … }; static struct acpi_table_viot *viot; static LIST_HEAD(viot_iommus); static LIST_HEAD(viot_pci_ranges); static LIST_HEAD(viot_mmio_endpoints); static int __init viot_check_bounds(const struct acpi_viot_header *hdr) { … } static int __init viot_get_pci_iommu_fwnode(struct viot_iommu *viommu, u16 segment, u16 bdf) { … } static int __init viot_get_mmio_iommu_fwnode(struct viot_iommu *viommu, u64 address) { … } static struct viot_iommu * __init viot_get_iommu(unsigned int offset) { … } static int __init viot_parse_node(const struct acpi_viot_header *hdr) { … } /** * acpi_viot_early_init - Test the presence of VIOT and enable ACS * * If the VIOT does exist, ACS must be enabled. This cannot be * done in acpi_viot_init() which is called after the bus scan */ void __init acpi_viot_early_init(void) { … } /** * acpi_viot_init - Parse the VIOT table * * Parse the VIOT table, prepare the list of endpoints to be used during DMA * setup of devices. */ void __init acpi_viot_init(void) { … } static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu, u32 epid) { … } static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) { … } static int viot_mmio_dev_iommu_init(struct platform_device *pdev) { … } /** * viot_iommu_configure - Setup IOMMU ops for an endpoint described by VIOT * @dev: the endpoint * * Return: 0 on success, <0 on failure */ int viot_iommu_configure(struct device *dev) { … }