Commit 4ff4252a authored by Frank Li's avatar Frank Li Committed by Bjorn Helgaas
Browse files

PCI: endpoint: Add pci_epf_align_inbound_addr() helper for inbound address alignment



Add pci_epf_align_inbound_addr() to align the inbound addresses according
to PCI BAR alignment requirements. The aligned base address and offset are
returned via 'base' and 'off' parameters.

Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
[mani: reworded kernel-doc and commit message]
Signed-off-by: default avatarManivannan Sadhasivam <mani@kernel.org>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Tested-by: default avatarNiklas Cassel <cassel@kernel.org>
Link: https://patch.msgid.link/20250710-ep-msi-v21-5-57683fc7fb25@nxp.com
parent c8223922
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -477,6 +477,44 @@ struct pci_epf *pci_epf_create(const char *name)
}
EXPORT_SYMBOL_GPL(pci_epf_create);

/**
 * pci_epf_align_inbound_addr() - Align the given address based on the BAR
 *				  alignment requirement
 * @epf: the EPF device
 * @addr: inbound address to be aligned
 * @bar: the BAR number corresponding to the given addr
 * @base: base address matching the @bar alignment requirement
 * @off: offset to be added to the @base address
 *
 * Helper function to align input @addr based on BAR's alignment requirement.
 * The aligned base address and offset are returned via @base and @off.
 *
 * NOTE: The pci_epf_alloc_space() function already accounts for alignment.
 * This API is primarily intended for use with other memory regions not
 * allocated by pci_epf_alloc_space(), such as peripheral register spaces or
 * the message address of a platform MSI controller.
 *
 * Return: 0 on success, errno otherwise.
 */
int pci_epf_align_inbound_addr(struct pci_epf *epf, enum pci_barno bar,
			       u64 addr, dma_addr_t *base, size_t *off)
{
	/*
	 * Most EP controllers require the BAR start address to be aligned to
	 * the BAR size, because they mask off the lower bits.
	 *
	 * Alignment to BAR size also works for controllers that support
	 * unaligned addresses.
	 */
	u64 align = epf->bar[bar].size;

	*base = round_down(addr, align);
	*off = addr & (align - 1);

	return 0;
}
EXPORT_SYMBOL_GPL(pci_epf_align_inbound_addr);

static void pci_epf_dev_release(struct device *dev)
{
	struct pci_epf *epf = to_pci_epf(dev);
+3 −0
Original line number Diff line number Diff line
@@ -241,6 +241,9 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
			  enum pci_epc_interface_type type);
void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
			enum pci_epc_interface_type type);

int pci_epf_align_inbound_addr(struct pci_epf *epf, enum pci_barno bar,
			       u64 addr, dma_addr_t *base, size_t *off);
int pci_epf_bind(struct pci_epf *epf);
void pci_epf_unbind(struct pci_epf *epf);
int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf);