]> Gentwo Git Trees - linux/.git/commitdiff
PCI: endpoint: Add pci_epf_get_required_bar_size() helper
authorFrank Li <Frank.Li@nxp.com>
Wed, 15 Oct 2025 15:27:29 +0000 (11:27 -0400)
committerManivannan Sadhasivam <mani@kernel.org>
Mon, 27 Oct 2025 14:34:51 +0000 (20:04 +0530)
Introduce pci_epf_get_required_bar_size() helper to get the required BAR
size and backing memory size. This helper will be used to set a fixed MMIO
address as the backing memory for a BAR.

Since this helper returns both BAR size and the aligned memory size, use
two parameters, 'bar_size' and 'aligned_mem_size' to avoid confusion.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
[mani: renamed helper to pci_epf_get_required_bar_size(), reworded description]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Link: https://patch.msgid.link/20251015-vntb_msi_doorbell-v6-2-9230298b1910@nxp.com
drivers/pci/endpoint/pci-epf-core.c

index 214e3f6e6d0d5a216c3469b8ff47908414cd1286..ec20aabb7f759199e4a394c6d33a5eb20badb6b9 100644 (file)
@@ -208,6 +208,48 @@ void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
 }
 EXPORT_SYMBOL_GPL(pci_epf_remove_vepf);
 
+static int pci_epf_get_required_bar_size(struct pci_epf *epf, size_t *bar_size,
+                               size_t *aligned_mem_size,
+                               enum pci_barno bar,
+                               const struct pci_epc_features *epc_features,
+                               enum pci_epc_interface_type type)
+{
+       u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
+       size_t align = epc_features->align;
+       size_t size = *bar_size;
+
+       if (size < 128)
+               size = 128;
+
+       /* According to PCIe base spec, min size for a resizable BAR is 1 MB. */
+       if (epc_features->bar[bar].type == BAR_RESIZABLE && size < SZ_1M)
+               size = SZ_1M;
+
+       if (epc_features->bar[bar].type == BAR_FIXED && bar_fixed_size) {
+               if (size > bar_fixed_size) {
+                       dev_err(&epf->dev,
+                               "requested BAR size is larger than fixed size\n");
+                       return -ENOMEM;
+               }
+               size = bar_fixed_size;
+       } else {
+               /* BAR size must be power of two */
+               size = roundup_pow_of_two(size);
+       }
+
+       *bar_size = size;
+
+       /*
+        * The EPC's BAR start address must meet alignment requirements. In most
+        * cases, the alignment will match the BAR size. However, differences
+        * can occur—for example, when the fixed BAR size (e.g., 128 bytes) is
+        * smaller than the required alignment (e.g., 4 KB).
+        */
+       *aligned_mem_size = align ? ALIGN(size, align) : size;
+
+       return 0;
+}
+
 /**
  * pci_epf_free_space() - free the allocated PCI EPF register space
  * @epf: the EPF device from whom to free the memory
@@ -264,40 +306,16 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
                          const struct pci_epc_features *epc_features,
                          enum pci_epc_interface_type type)
 {
-       u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
-       size_t mem_size, align = epc_features->align;
        struct pci_epf_bar *epf_bar;
        dma_addr_t phys_addr;
        struct pci_epc *epc;
        struct device *dev;
+       size_t mem_size;
        void *space;
 
-       if (size < 128)
-               size = 128;
-
-       /* According to PCIe base spec, min size for a resizable BAR is 1 MB. */
-       if (epc_features->bar[bar].type == BAR_RESIZABLE && size < SZ_1M)
-               size = SZ_1M;
-
-       if (epc_features->bar[bar].type == BAR_FIXED && bar_fixed_size) {
-               if (size > bar_fixed_size) {
-                       dev_err(&epf->dev,
-                               "requested BAR size is larger than fixed size\n");
-                       return NULL;
-               }
-               size = bar_fixed_size;
-       } else {
-               /* BAR size must be power of two */
-               size = roundup_pow_of_two(size);
-       }
-
-       /*
-        * Allocate enough memory to accommodate the iATU alignment
-        * requirement.  In most cases, this will be the same as .size but
-        * it might be different if, for example, the fixed size of a BAR
-        * is smaller than align.
-        */
-       mem_size = align ? ALIGN(size, align) : size;
+       if (pci_epf_get_required_bar_size(epf, &size, &mem_size, bar,
+                                         epc_features, type))
+               return NULL;
 
        if (type == PRIMARY_INTERFACE) {
                epc = epf->epc;