The mhp layer has alignment restrictions that may cause a failure in adding a large P2PMEM that has non-aligned number of pages. The new API pci_p2pdma_align_size will align the P2PMEM size to be inline with the mhp restrictions. Signed-off-by: Max Gurtovoy <mgurtovoy@xxxxxxxxxx> --- drivers/pci/p2pdma.c | 23 +++++++++++++++++++++++ include/linux/pci-p2pdma.h | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 196382630363..d232bc4ada2b 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -220,6 +220,29 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, } EXPORT_SYMBOL_GPL(pci_p2pdma_add_resource); +/** + * pci_p2pdma_align_size - align p2p memory size + * @size: size of the initial memory to align before adding. + * + * The size will be aligned according to mph alignment rules. This function + * should be called before adding new p2pdma resource since non-aligned memory + * will not be added. + */ +size_t pci_p2pdma_align_size(size_t size) +{ + unsigned int min_align, nr_pages; + + min_align = mhp_get_min_align(); + nr_pages = size >> PAGE_SHIFT; + if (!IS_ALIGNED(nr_pages, min_align)) { + nr_pages = ALIGN_DOWN(nr_pages, min_align); + size = nr_pages << PAGE_SHIFT; + } + + return size; +} +EXPORT_SYMBOL_GPL(pci_p2pdma_align_size); + /* * Note this function returns the parent PCI device with a * reference taken. It is the caller's responsibility to drop diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h index 8318a97c9c61..33a8fce52bec 100644 --- a/include/linux/pci-p2pdma.h +++ b/include/linux/pci-p2pdma.h @@ -38,6 +38,7 @@ int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev, bool *use_p2pdma); ssize_t pci_p2pdma_enable_show(char *page, struct pci_dev *p2p_dev, bool use_p2pdma); +size_t pci_p2pdma_align_size(size_t size); #else /* CONFIG_PCI_P2PDMA */ static inline int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, u64 offset) @@ -105,6 +106,10 @@ static inline ssize_t pci_p2pdma_enable_show(char *page, { return sprintf(page, "none\n"); } +static inline size_t pci_p2pdma_align_size(size_t size) +{ + return 0; +} #endif /* CONFIG_PCI_P2PDMA */ -- 2.18.1