Unverified Commit f3a29640 authored by Ajay Agarwal's avatar Ajay Agarwal Committed by Krzysztof Wilczyński
Browse files

PCI: dwc: Strengthen the MSI address allocation logic

There can be platforms that do not use/have 32-bit DMA addresses.
The current implementation of 32-bit IOVA allocation can fail for
such platforms, eventually leading to the probe failure.

Try to allocate a 32-bit msi_data. If this allocation fails,
attempt a 64-bit address allocation. Please note that if the
64-bit MSI address is allocated, then the EPs supporting 32-bit
MSI address only will not work.

Link: https://lore.kernel.org/linux-pci/20240221153840.1789979-1-ajayagarwal@google.com


Tested-by: default avatarWill McVicker <willmcvicker@google.com>
Signed-off-by: default avatarAjay Agarwal <ajayagarwal@google.com>
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: default avatarSerge Semin <fancer.lancer@gmail.com>
Reviewed-by: default avatarWill McVicker <willmcvicker@google.com>
parent 6613476e
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -328,7 +328,7 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
	struct device *dev = pci->dev;
	struct platform_device *pdev = to_platform_device(dev);
	u64 *msi_vaddr;
	u64 *msi_vaddr = NULL;
	int ret;
	u32 ctrl, num_ctrls;

@@ -379,16 +379,21 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
	 * memory.
	 */
	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
	if (ret)
		dev_warn(dev, "Failed to set DMA mask to 32-bit. Devices with only 32-bit MSI support may not work properly\n");
	if (!ret)
		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
						GFP_KERNEL);

	if (!msi_vaddr) {
		dev_warn(dev, "Failed to allocate 32-bit MSI address\n");
		dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
		msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
						GFP_KERNEL);
		if (!msi_vaddr) {
		dev_err(dev, "Failed to alloc and map MSI data\n");
			dev_err(dev, "Failed to allocate MSI address\n");
			dw_pcie_free_msi(pp);
			return -ENOMEM;
		}
	}

	return 0;
}