Unverified Commit e73ea1c2 authored by Damien Le Moal's avatar Damien Le Moal Committed by Krzysztof Wilczyński
Browse files

PCI: dwc: endpoint: Implement the pci_epc_ops::align_addr() operation

The function dw_pcie_prog_outbound_atu() used to program outbound ATU
entries for mapping RC PCI addresses to local CPU addresses does not
allow PCI addresses that are not aligned to the value of region_align
of struct dw_pcie. This value is determined from the iATU hardware
registers during probing of the iATU (done by dw_pcie_iatu_detect()).
This value is thus valid for all DWC PCIe controllers, and valid
regardless of the hardware configuration used when synthesizing the
DWC PCIe controller.

Implement the ->align_addr() endpoint controller operation to allow
this mapping alignment to be transparently handled by endpoint function
drivers through the function pci_epc_mem_map().

Link: https://lore.kernel.org/linux-pci/20241012113246.95634-7-dlemoal@kernel.org
Link: https://lore.kernel.org/linux-pci/20241015090712.112674-1-dlemoal@kernel.org
Link: https://lore.kernel.org/linux-pci/20241017132052.4014605-5-cassel@kernel.org


Co-developed-by: default avatarNiklas Cassel <cassel@kernel.org>
Signed-off-by: default avatarDamien Le Moal <dlemoal@kernel.org>
[mani: squashed the patch that changed phy_addr_t to u64]
Signed-off-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
[kwilczynski: squashed patch that updated the pci_size variable]
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
parent 08cac100
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -268,6 +268,20 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
	return -EINVAL;
}

static u64 dw_pcie_ep_align_addr(struct pci_epc *epc, u64 pci_addr,
				 size_t *pci_size, size_t *offset)
{
	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
	u64 mask = pci->region_align - 1;
	size_t ofst = pci_addr & mask;

	*pci_size = ALIGN(ofst + *pci_size, epc->mem->window.page_size);
	*offset = ofst;

	return pci_addr & ~mask;
}

static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
				  phys_addr_t addr)
{
@@ -444,6 +458,7 @@ static const struct pci_epc_ops epc_ops = {
	.write_header		= dw_pcie_ep_write_header,
	.set_bar		= dw_pcie_ep_set_bar,
	.clear_bar		= dw_pcie_ep_clear_bar,
	.align_addr		= dw_pcie_ep_align_addr,
	.map_addr		= dw_pcie_ep_map_addr,
	.unmap_addr		= dw_pcie_ep_unmap_addr,
	.set_msi		= dw_pcie_ep_set_msi,