Skip to content

Commit 4ff4252

Browse files
nxpfranklibjorn-helgaas
authored andcommitted
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: Frank Li <Frank.Li@nxp.com> [mani: reworded kernel-doc and commit message] Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: Niklas Cassel <cassel@kernel.org> Link: https://patch.msgid.link/20250710-ep-msi-v21-5-57683fc7fb25@nxp.com
1 parent c822392 commit 4ff4252

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

drivers/pci/endpoint/pci-epf-core.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,44 @@ struct pci_epf *pci_epf_create(const char *name)
477477
}
478478
EXPORT_SYMBOL_GPL(pci_epf_create);
479479

480+
/**
481+
* pci_epf_align_inbound_addr() - Align the given address based on the BAR
482+
* alignment requirement
483+
* @epf: the EPF device
484+
* @addr: inbound address to be aligned
485+
* @bar: the BAR number corresponding to the given addr
486+
* @base: base address matching the @bar alignment requirement
487+
* @off: offset to be added to the @base address
488+
*
489+
* Helper function to align input @addr based on BAR's alignment requirement.
490+
* The aligned base address and offset are returned via @base and @off.
491+
*
492+
* NOTE: The pci_epf_alloc_space() function already accounts for alignment.
493+
* This API is primarily intended for use with other memory regions not
494+
* allocated by pci_epf_alloc_space(), such as peripheral register spaces or
495+
* the message address of a platform MSI controller.
496+
*
497+
* Return: 0 on success, errno otherwise.
498+
*/
499+
int pci_epf_align_inbound_addr(struct pci_epf *epf, enum pci_barno bar,
500+
u64 addr, dma_addr_t *base, size_t *off)
501+
{
502+
/*
503+
* Most EP controllers require the BAR start address to be aligned to
504+
* the BAR size, because they mask off the lower bits.
505+
*
506+
* Alignment to BAR size also works for controllers that support
507+
* unaligned addresses.
508+
*/
509+
u64 align = epf->bar[bar].size;
510+
511+
*base = round_down(addr, align);
512+
*off = addr & (align - 1);
513+
514+
return 0;
515+
}
516+
EXPORT_SYMBOL_GPL(pci_epf_align_inbound_addr);
517+
480518
static void pci_epf_dev_release(struct device *dev)
481519
{
482520
struct pci_epf *epf = to_pci_epf(dev);

include/linux/pci-epf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
241241
enum pci_epc_interface_type type);
242242
void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
243243
enum pci_epc_interface_type type);
244+
245+
int pci_epf_align_inbound_addr(struct pci_epf *epf, enum pci_barno bar,
246+
u64 addr, dma_addr_t *base, size_t *off);
244247
int pci_epf_bind(struct pci_epf *epf);
245248
void pci_epf_unbind(struct pci_epf *epf);
246249
int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf);

0 commit comments

Comments
 (0)