PCI: designware-ep: Pre-allocate memory for MSI in dw_pcie_ep_init

Certain SoCs need to map the MSI address in raise_irq.
To map an address, you first need to call pci_epc_mem_alloc_addr(),
however, pci_epc_mem_alloc_addr() calls ioremap() (which can sleep).

Since raise_irq is only called from atomic context, we can't call
pci_epc_mem_alloc_addr() from raise_irq.

Pre-allocate a page in dw_pcie_ep_init(), so that this page can later
be used to map/unmap the MSI address in raise_irq.

Tested-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Joao Pinto <jpinto@synopsys.com>
This commit is contained in:
Niklas Cassel 2017-12-20 00:29:25 +01:00 committed by Lorenzo Pieralisi
parent 1cab826b30
commit 2fd0c9d966
2 changed files with 12 additions and 0 deletions

View File

@ -286,6 +286,9 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
{ {
struct pci_epc *epc = ep->epc; struct pci_epc *epc = ep->epc;
pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
epc->mem->page_size);
pci_epc_mem_exit(epc); pci_epc_mem_exit(epc);
} }
@ -341,6 +344,13 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
return ret; return ret;
} }
ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys,
epc->mem->page_size);
if (!ep->msi_mem) {
dev_err(dev, "Failed to reserve memory for MSI\n");
return -ENOMEM;
}
ep->epc = epc; ep->epc = epc;
epc_set_drvdata(epc, ep); epc_set_drvdata(epc, ep);
dw_pcie_setup(pci); dw_pcie_setup(pci);

View File

@ -198,6 +198,8 @@ struct dw_pcie_ep {
unsigned long ob_window_map; unsigned long ob_window_map;
u32 num_ib_windows; u32 num_ib_windows;
u32 num_ob_windows; u32 num_ob_windows;
void __iomem *msi_mem;
phys_addr_t msi_mem_phys;
}; };
struct dw_pcie_ops { struct dw_pcie_ops {