PCI: tegra: Support MSI 64-bit addressing
authorThierry Reding <treding@nvidia.com>
Thu, 4 May 2017 20:10:31 +0000 (22:10 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Sun, 2 Jul 2017 23:46:20 +0000 (18:46 -0500)
The MSI target address can reside beyond the 32-bit boundary on devices
with more than 2 GiB of system memory.  The PCI host bridge on Tegra can
easily support 64-bit addresses, so make sure to pass the upper 32 bits of
the target address to endpoints when allocating MSI entries.

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 0dadb81..1d1d87e 100644 (file)
@@ -235,6 +235,7 @@ struct tegra_msi {
        struct irq_domain *domain;
        unsigned long pages;
        struct mutex lock;
+       u64 phys;
        int irq;
 };
 
@@ -1448,9 +1449,8 @@ static int tegra_msi_setup_irq(struct msi_controller *chip,
 
        irq_set_msi_desc(irq, desc);
 
-       msg.address_lo = virt_to_phys((void *)msi->pages);
-       /* 32 bit address only */
-       msg.address_hi = 0;
+       msg.address_lo = lower_32_bits(msi->phys);
+       msg.address_hi = upper_32_bits(msi->phys);
        msg.data = hwirq;
 
        pci_write_msi_msg(irq, &msg);
@@ -1499,7 +1499,6 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
        const struct tegra_pcie_soc *soc = pcie->soc;
        struct tegra_msi *msi = &pcie->msi;
        struct device *dev = pcie->dev;
-       unsigned long base;
        int err;
        u32 reg;
 
@@ -1533,10 +1532,10 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
 
        /* setup AFI/FPCI range */
        msi->pages = __get_free_pages(GFP_KERNEL, 0);
-       base = virt_to_phys((void *)msi->pages);
+       msi->phys = virt_to_phys((void *)msi->pages);
 
-       afi_writel(pcie, base >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST);
-       afi_writel(pcie, base, AFI_MSI_AXI_BAR_ST);
+       afi_writel(pcie, msi->phys >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST);
+       afi_writel(pcie, msi->phys, AFI_MSI_AXI_BAR_ST);
        /* this register is in 4K increments */
        afi_writel(pcie, 1, AFI_MSI_BAR_SZ);