]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
PCI: tegra: Do not allocate MSI target memory
authorThierry Reding <treding@nvidia.com>
Thu, 4 May 2017 20:10:32 +0000 (22:10 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Sun, 2 Jul 2017 23:46:20 +0000 (18:46 -0500)
The PCI host bridge found on Tegra SoCs doesn't require the MSI target
address to be backed by physical system memory.  Writes are intercepted
within the controller and never make it to the memory pointed to.

Since no actual system memory is required, remove the allocation of a
single page and hardcode the MSI target address with a special address that
maps to the last 4 KiB page within the range that is reserved for system
memory and memory-mapped I/O in the FPCI address map.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Stephen Warren <swarren@nvidia.com>
drivers/pci/host/pci-tegra.c

index 1d1d87e8bcbf3f6706d12da76cd2aa4da8c6fa10..b3722b7709df88a228fe736110be37b5ddbbe892 100644 (file)
@@ -233,7 +233,6 @@ struct tegra_msi {
        struct msi_controller chip;
        DECLARE_BITMAP(used, INT_PCI_MSI_NR);
        struct irq_domain *domain;
-       unsigned long pages;
        struct mutex lock;
        u64 phys;
        int irq;
@@ -1530,9 +1529,22 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
                goto err;
        }
 
-       /* setup AFI/FPCI range */
-       msi->pages = __get_free_pages(GFP_KERNEL, 0);
-       msi->phys = virt_to_phys((void *)msi->pages);
+       /*
+        * The PCI host bridge on Tegra contains some logic that intercepts
+        * MSI writes, which means that the MSI target address doesn't have
+        * to point to actual physical memory. Rather than allocating one 4
+        * KiB page of system memory that's never used, we can simply pick
+        * an arbitrary address within an area reserved for system memory
+        * in the FPCI address map.
+        *
+        * However, in order to avoid confusion, we pick an address that
+        * doesn't map to physical memory. The FPCI address map reserves a
+        * 1012 GiB region for system memory and memory-mapped I/O. Since
+        * none of the Tegra SoCs that contain this PCI host bridge can
+        * address more than 16 GiB of system memory, the last 4 KiB of
+        * these 1012 GiB is a good candidate.
+        */
+       msi->phys = 0xfcfffff000;
 
        afi_writel(pcie, msi->phys >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST);
        afi_writel(pcie, msi->phys, AFI_MSI_AXI_BAR_ST);
@@ -1584,8 +1596,6 @@ static int tegra_pcie_disable_msi(struct tegra_pcie *pcie)
        afi_writel(pcie, 0, AFI_MSI_EN_VEC6);
        afi_writel(pcie, 0, AFI_MSI_EN_VEC7);
 
-       free_pages(msi->pages, 0);
-
        if (msi->irq > 0)
                free_irq(msi->irq, pcie);