Commit 3dcb861d authored by Eric Auger's avatar Eric Auger Committed by Rafael J. Wysocki
Browse files

ACPI: VIOT: Fix ACS setup



Currently acpi_viot_init() gets called after the pci
device has been scanned and pci_enable_acs() has been called.
So pci_request_acs() fails to be taken into account leading
to wrong single iommu group topologies when dealing with
multi-function root ports for instance.

We cannot simply move the acpi_viot_init() earlier, similarly
as the IORT init because the VIOT parsing relies on the pci
scan. However we can detect VIOT is present earlier and in
such a case, request ACS. Introduce a new acpi_viot_early_init()
routine that allows to call pci_request_acs() before the scan.

While at it, guard the call to pci_request_acs() with #ifdef
CONFIG_PCI.

Fixes: 3cf48554 ("ACPI: Add driver for the VIOT table")
Signed-off-by: default avatarEric Auger <eric.auger@redhat.com>
Reported-by: default avatarJin Liu <jinl@redhat.com>
Reviewed-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Tested-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 88084a3d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1400,6 +1400,7 @@ static int __init acpi_init(void)

	pci_mmcfg_late_init();
	acpi_iort_init();
	acpi_viot_early_init();
	acpi_hest_init();
	acpi_ghes_init();
	acpi_scan_init();
+20 −6
Original line number Diff line number Diff line
@@ -248,6 +248,26 @@ static int __init viot_parse_node(const struct acpi_viot_header *hdr)
	return ret;
}

/**
 * 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)
{
#ifdef CONFIG_PCI
	acpi_status status;
	struct acpi_table_header *hdr;

	status = acpi_get_table(ACPI_SIG_VIOT, 0, &hdr);
	if (ACPI_FAILURE(status))
		return;
	pci_request_acs();
	acpi_put_table(hdr);
#endif
}

/**
 * acpi_viot_init - Parse the VIOT table
 *
@@ -319,12 +339,6 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)
			epid = ((domain_nr - ep->segment_start) << 16) +
				dev_id - ep->bdf_start + ep->endpoint_id;

			/*
			 * If we found a PCI range managed by the viommu, we're
			 * the one that has to request ACS.
			 */
			pci_request_acs();

			return viot_dev_iommu_init(&pdev->dev, ep->viommu,
						   epid);
		}
+2 −0
Original line number Diff line number Diff line
@@ -6,9 +6,11 @@
#include <linux/acpi.h>

#ifdef CONFIG_ACPI_VIOT
void __init acpi_viot_early_init(void);
void __init acpi_viot_init(void);
int viot_iommu_configure(struct device *dev);
#else
static inline void acpi_viot_early_init(void) {}
static inline void acpi_viot_init(void) {}
static inline int viot_iommu_configure(struct device *dev)
{