Merge branch 'remotes/lorenzo/pci/tegra'

- Use DMA-API to get tegra MSI address to prevent device DMA from
    generating unwanted MSIs (Vidya Sagar)

* remotes/lorenzo/pci/tegra:
  PCI: tegra: Use the DMA-API to get the MSI address
This commit is contained in:
Bjorn Helgaas 2019-05-13 18:34:43 -05:00
commit cdf4315502

View File

@ -231,9 +231,9 @@ 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;
void *virt;
dma_addr_t phys;
int irq;
};
@ -1536,7 +1536,7 @@ static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)
err = platform_get_irq_byname(pdev, "msi");
if (err < 0) {
dev_err(dev, "failed to get IRQ: %d\n", err);
goto err;
goto free_irq_domain;
}
msi->irq = err;
@ -1545,17 +1545,35 @@ static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)
tegra_msi_irq_chip.name, pcie);
if (err < 0) {
dev_err(dev, "failed to request IRQ: %d\n", err);
goto err;
goto free_irq_domain;
}
/* Though the PCIe controller can address >32-bit address space, to
* facilitate endpoints that support only 32-bit MSI target address,
* the mask is set to 32-bit to make sure that MSI target address is
* always a 32-bit address
*/
err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (err < 0) {
dev_err(dev, "failed to set DMA coherent mask: %d\n", err);
goto free_irq;
}
msi->virt = dma_alloc_attrs(dev, PAGE_SIZE, &msi->phys, GFP_KERNEL,
DMA_ATTR_NO_KERNEL_MAPPING);
if (!msi->virt) {
dev_err(dev, "failed to allocate DMA memory for MSI\n");
err = -ENOMEM;
goto free_irq;
}
/* setup AFI/FPCI range */
msi->pages = __get_free_pages(GFP_KERNEL, 0);
msi->phys = virt_to_phys((void *)msi->pages);
host->msi = &msi->chip;
return 0;
err:
free_irq:
free_irq(msi->irq, pcie);
free_irq_domain:
irq_domain_remove(msi->domain);
return err;
}
@ -1592,7 +1610,8 @@ static void tegra_pcie_msi_teardown(struct tegra_pcie *pcie)
struct tegra_msi *msi = &pcie->msi;
unsigned int i, irq;
free_pages(msi->pages, 0);
dma_free_attrs(pcie->dev, PAGE_SIZE, msi->virt, msi->phys,
DMA_ATTR_NO_KERNEL_MAPPING);
if (msi->irq > 0)
free_irq(msi->irq, pcie);