[PATCH 1/2] PCI: endpoint: Enhance pci_epf_alloc_space() and rename to pci_epf_set_inbound_space()

Frank Li posted 2 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH 1/2] PCI: endpoint: Enhance pci_epf_alloc_space() and rename to pci_epf_set_inbound_space()
Posted by Frank Li 1 month, 2 weeks ago
Enhance pci_epf_alloc_space() to handle setting any physical address as
inbound memory space, such as an MSI message base address. The function
already accounts for different alignment requirements for different BARs,
so reuse this logic and rename the function to pci_epf_set_inbound_space().

Make pci_epf_alloc_space() inline and call pci_epf_set_inbound_space() with
from_space set to true to maintain compatibility.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
---
 drivers/pci/endpoint/pci-epf-core.c | 69 ++++++++++++++++++++++++++++++-------
 include/linux/pci-epc.h             |  5 ---
 include/linux/pci-epf.h             | 35 ++++++++++++++++---
 3 files changed, 87 insertions(+), 22 deletions(-)

diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index d54e18872aefc07c655c94c104a347328ff7a432..5b802b1ea3e28a32e38f4ab6a649cb97a2f29b95 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -249,20 +249,26 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
 EXPORT_SYMBOL_GPL(pci_epf_free_space);
 
 /**
- * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
+ * pci_epf_set_inbound_space() - set memory for the PCI EPF inbound address space
  * @epf: the EPF device to whom allocate the memory
  * @size: the size of the memory that has to be allocated
  * @bar: the BAR number corresponding to the allocated register space
  * @epc_features: the features provided by the EPC specific to this EPF
  * @type: Identifies if the allocation is for primary EPC or secondary EPC
+ * @from_memory: allocate from system memory
+ * @inbound_addr: Any physical address space such as MSI message address that
+ *                work as inbound address space. from_memory need be false.
  *
  * Invoke to allocate memory for the PCI EPF register space.
  * Flag PCI_BASE_ADDRESS_MEM_TYPE_64 will automatically get set if the BAR
  * can only be a 64-bit BAR, or if the requested size is larger than 2 GB.
  */
-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)
+int pci_epf_set_inbound_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,
+			      bool from_memory,
+			      dma_addr_t inbound_addr)
 {
 	u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
 	size_t aligned_size, align = epc_features->align;
@@ -270,7 +276,32 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 	dma_addr_t phys_addr;
 	struct pci_epc *epc;
 	struct device *dev;
-	void *space;
+	void *space = NULL;
+	dma_addr_t up;
+
+	up = inbound_addr + size - 1;
+
+	/*
+	 *  Bits:            15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+	 *  Inbound_addr:    U  U  U  U  U  U  0 X X X X X X X X X
+	 *  Up:              U  U  U  U  U  U  1 X X X X X X X X X
+	 *
+	 *  U means address bits have not change in Range [Inbound_Addr, Up]
+	 *  X means bit 0 or 1.
+	 *
+	 *  Inbound_addr^Up  0  0  0  0  0  0  1 X X X X X X X X X
+	 *  Find first bit 1 pos from MSB, 2 ^ pos windows will cover
+	 *  [Inbound_Addr, Up] range.
+	 */
+	if (!from_memory) {
+		int pos;
+
+		for (pos = sizeof(dma_addr_t) - 1; pos > 0; pos--)
+			if ((up ^ inbound_addr) & BIT_ULL(pos))
+				break;
+
+		size = 1 << pos;
+	}
 
 	if (size < 128)
 		size = 128;
@@ -283,7 +314,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 		if (size > bar_fixed_size) {
 			dev_err(&epf->dev,
 				"requested BAR size is larger than fixed size\n");
-			return NULL;
+			return -EINVAL;
 		}
 		size = bar_fixed_size;
 	} else {
@@ -308,13 +339,25 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 	}
 
 	dev = epc->dev.parent;
-	space = dma_alloc_coherent(dev, aligned_size, &phys_addr, GFP_KERNEL);
-	if (!space) {
-		dev_err(dev, "failed to allocate mem space\n");
-		return NULL;
+
+	if (from_memory) {
+		space = dma_alloc_coherent(dev, aligned_size,
+					   &phys_addr, GFP_KERNEL);
+		if (!space) {
+			dev_err(dev, "failed to allocate mem space\n");
+			return -ENOMEM;
+		}
+	}
+
+	epf_bar[bar].phys_addr = from_memory ?
+			phys_addr : ALIGN_DOWN(inbound_addr, aligned_size);
+
+	if (!from_memory && (epf_bar[bar].phys_addr + size < up)) {
+		dev_err(&epf->dev,
+			"Given bar can't fit required inbound memory region\n");
+		return -EINVAL;
 	}
 
-	epf_bar[bar].phys_addr = phys_addr;
 	epf_bar[bar].addr = space;
 	epf_bar[bar].size = size;
 	epf_bar[bar].aligned_size = aligned_size;
@@ -324,9 +367,9 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 	else
 		epf_bar[bar].flags |= PCI_BASE_ADDRESS_MEM_TYPE_32;
 
-	return space;
+	return 0;
 }
-EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
+EXPORT_SYMBOL_GPL(pci_epf_set_inbound_space);
 
 static void pci_epf_remove_cfs(struct pci_epf_driver *driver)
 {
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 4286bfdbfdfad2754d763be2b8474e5d2d403a1f..5f1d8787c3bb7a6130adb54c079a48c82d5afcf4 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -13,11 +13,6 @@
 
 struct pci_epc;
 
-enum pci_epc_interface_type {
-	UNKNOWN_INTERFACE = -1,
-	PRIMARY_INTERFACE,
-	SECONDARY_INTERFACE,
-};
 
 static inline const char *
 pci_epc_interface_string(enum pci_epc_interface_type type)
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
index 2e85504ba2baf93827224884ca19ae2bd0e6906b..4311a8ba1081b8a8aa327c8ed10f9c5d9af2feba 100644
--- a/include/linux/pci-epf.h
+++ b/include/linux/pci-epf.h
@@ -17,7 +17,12 @@
 
 struct pci_epf;
 struct pci_epc_features;
-enum pci_epc_interface_type;
+
+enum pci_epc_interface_type {
+	UNKNOWN_INTERFACE = -1,
+	PRIMARY_INTERFACE,
+	SECONDARY_INTERFACE,
+};
 
 enum pci_barno {
 	NO_BAR = -1,
@@ -236,9 +241,31 @@ void pci_epf_destroy(struct pci_epf *epf);
 int __pci_epf_register_driver(struct pci_epf_driver *driver,
 			      struct module *owner);
 void pci_epf_unregister_driver(struct pci_epf_driver *driver);
-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);
+
+int pci_epf_set_inbound_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,
+			      bool from_memory,
+			      dma_addr_t inbound_addr);
+
+static inline 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)
+{
+	int ret;
+
+	ret = pci_epf_set_inbound_space(epf, size, bar, epc_features, type,
+					true, 0);
+
+	if (ret)
+		return NULL;
+
+	return type == PRIMARY_INTERFACE ? epf->bar[bar].addr :
+					   epf->sec_epc_bar[bar].addr;
+}
+
 void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
 			enum pci_epc_interface_type type);
 

-- 
2.34.1
Re: [PATCH 1/2] PCI: endpoint: Enhance pci_epf_alloc_space() and rename to pci_epf_set_inbound_space()
Posted by Manivannan Sadhasivam 1 month ago
On Fri, Aug 15, 2025 at 06:20:53PM GMT, Frank Li wrote:
> Enhance pci_epf_alloc_space() to handle setting any physical address as
> inbound memory space, such as an MSI message base address. The function
> already accounts for different alignment requirements for different BARs,
> so reuse this logic and rename the function to pci_epf_set_inbound_space().
> 

I don't think combining both APIs is a good idea. One allocates space for
inbound memory/populates epf_bar and another reuses existing memory/populates
epf_bar. Combining both, logically makes little sense and another makes the code
messy.

If you want to reuse the alignment checks and epf_bar setting from
pci_epf_alloc_space(), then create a separate helper(s) out of it and call from
both APIs.

> Make pci_epf_alloc_space() inline and call pci_epf_set_inbound_space() with
> from_space set to true to maintain compatibility.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> ---
>  drivers/pci/endpoint/pci-epf-core.c | 69 ++++++++++++++++++++++++++++++-------
>  include/linux/pci-epc.h             |  5 ---
>  include/linux/pci-epf.h             | 35 ++++++++++++++++---
>  3 files changed, 87 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
> index d54e18872aefc07c655c94c104a347328ff7a432..5b802b1ea3e28a32e38f4ab6a649cb97a2f29b95 100644
> --- a/drivers/pci/endpoint/pci-epf-core.c
> +++ b/drivers/pci/endpoint/pci-epf-core.c
> @@ -249,20 +249,26 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
>  EXPORT_SYMBOL_GPL(pci_epf_free_space);
>  
>  /**
> - * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
> + * pci_epf_set_inbound_space() - set memory for the PCI EPF inbound address space
>   * @epf: the EPF device to whom allocate the memory
>   * @size: the size of the memory that has to be allocated
>   * @bar: the BAR number corresponding to the allocated register space
>   * @epc_features: the features provided by the EPC specific to this EPF
>   * @type: Identifies if the allocation is for primary EPC or secondary EPC
> + * @from_memory: allocate from system memory
> + * @inbound_addr: Any physical address space such as MSI message address that
> + *                work as inbound address space. from_memory need be false.
>   *
>   * Invoke to allocate memory for the PCI EPF register space.
>   * Flag PCI_BASE_ADDRESS_MEM_TYPE_64 will automatically get set if the BAR
>   * can only be a 64-bit BAR, or if the requested size is larger than 2 GB.
>   */
> -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)
> +int pci_epf_set_inbound_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,
> +			      bool from_memory,
> +			      dma_addr_t inbound_addr)
>  {
>  	u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
>  	size_t aligned_size, align = epc_features->align;
> @@ -270,7 +276,32 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
>  	dma_addr_t phys_addr;
>  	struct pci_epc *epc;
>  	struct device *dev;
> -	void *space;
> +	void *space = NULL;
> +	dma_addr_t up;
> +
> +	up = inbound_addr + size - 1;
> +
> +	/*
> +	 *  Bits:            15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +	 *  Inbound_addr:    U  U  U  U  U  U  0 X X X X X X X X X
> +	 *  Up:              U  U  U  U  U  U  1 X X X X X X X X X
> +	 *
> +	 *  U means address bits have not change in Range [Inbound_Addr, Up]
> +	 *  X means bit 0 or 1.
> +	 *
> +	 *  Inbound_addr^Up  0  0  0  0  0  0  1 X X X X X X X X X
> +	 *  Find first bit 1 pos from MSB, 2 ^ pos windows will cover
> +	 *  [Inbound_Addr, Up] range.

On what basis this size calculation is used?

- Mani

-- 
மணிவண்ணன் சதாசிவம்
Re: [PATCH 1/2] PCI: endpoint: Enhance pci_epf_alloc_space() and rename to pci_epf_set_inbound_space()
Posted by Frank Li 2 weeks, 4 days ago
On Sat, Aug 30, 2025 at 08:16:33PM +0530, Manivannan Sadhasivam wrote:
> On Fri, Aug 15, 2025 at 06:20:53PM GMT, Frank Li wrote:
> > Enhance pci_epf_alloc_space() to handle setting any physical address as
> > inbound memory space, such as an MSI message base address. The function
> > already accounts for different alignment requirements for different BARs,
> > so reuse this logic and rename the function to pci_epf_set_inbound_space().
> >
>
> I don't think combining both APIs is a good idea. One allocates space for
> inbound memory/populates epf_bar and another reuses existing memory/populates
> epf_bar. Combining both, logically makes little sense and another makes the code
> messy.
>
> If you want to reuse the alignment checks and epf_bar setting from
> pci_epf_alloc_space(), then create a separate helper(s) out of it and call from
> both APIs.
>
> > Make pci_epf_alloc_space() inline and call pci_epf_set_inbound_space() with
> > from_space set to true to maintain compatibility.
> >
> > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > ---
> > ---
> >  drivers/pci/endpoint/pci-epf-core.c | 69 ++++++++++++++++++++++++++++++-------
> >  include/linux/pci-epc.h             |  5 ---
> >  include/linux/pci-epf.h             | 35 ++++++++++++++++---
> >  3 files changed, 87 insertions(+), 22 deletions(-)
> >
> > diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
> > index d54e18872aefc07c655c94c104a347328ff7a432..5b802b1ea3e28a32e38f4ab6a649cb97a2f29b95 100644
> > --- a/drivers/pci/endpoint/pci-epf-core.c
> > +++ b/drivers/pci/endpoint/pci-epf-core.c
> > @@ -249,20 +249,26 @@ void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
> >  EXPORT_SYMBOL_GPL(pci_epf_free_space);
> >
> >  /**
> > - * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
> > + * pci_epf_set_inbound_space() - set memory for the PCI EPF inbound address space
> >   * @epf: the EPF device to whom allocate the memory
> >   * @size: the size of the memory that has to be allocated
> >   * @bar: the BAR number corresponding to the allocated register space
> >   * @epc_features: the features provided by the EPC specific to this EPF
> >   * @type: Identifies if the allocation is for primary EPC or secondary EPC
> > + * @from_memory: allocate from system memory
> > + * @inbound_addr: Any physical address space such as MSI message address that
> > + *                work as inbound address space. from_memory need be false.
> >   *
> >   * Invoke to allocate memory for the PCI EPF register space.
> >   * Flag PCI_BASE_ADDRESS_MEM_TYPE_64 will automatically get set if the BAR
> >   * can only be a 64-bit BAR, or if the requested size is larger than 2 GB.
> >   */
> > -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)
> > +int pci_epf_set_inbound_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,
> > +			      bool from_memory,
> > +			      dma_addr_t inbound_addr)
> >  {
> >  	u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
> >  	size_t aligned_size, align = epc_features->align;
> > @@ -270,7 +276,32 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
> >  	dma_addr_t phys_addr;
> >  	struct pci_epc *epc;
> >  	struct device *dev;
> > -	void *space;
> > +	void *space = NULL;
> > +	dma_addr_t up;
> > +
> > +	up = inbound_addr + size - 1;
> > +
> > +	/*
> > +	 *  Bits:            15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> > +	 *  Inbound_addr:    U  U  U  U  U  U  0 X X X X X X X X X
> > +	 *  Up:              U  U  U  U  U  U  1 X X X X X X X X X
> > +	 *
> > +	 *  U means address bits have not change in Range [Inbound_Addr, Up]
> > +	 *  X means bit 0 or 1.
> > +	 *
> > +	 *  Inbound_addr^Up  0  0  0  0  0  0  1 X X X X X X X X X
> > +	 *  Find first bit 1 pos from MSB, 2 ^ pos windows will cover
> > +	 *  [Inbound_Addr, Up] range.
>
> On what basis this size calculation is used?

Use to bar's base address and size. pci require size is 2^n
If set mmio space 0x1040..0x10a0 space, bar should be start from 0x1000,
size is at least 0x100 to cove 0x1040..0x10a0 space.

Frank

>
> - Mani
>
> --
> மணிவண்ணன் சதாசிவம்
Re: [PATCH 1/2] PCI: endpoint: Enhance pci_epf_alloc_space() and rename to pci_epf_set_inbound_space()
Posted by ALOK TIWARI 1 month ago

On 8/16/2025 3:50 AM, Frank Li wrote:
> +int pci_epf_set_inbound_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,
> +			      bool from_memory,
> +			      dma_addr_t inbound_addr)
>   {
>   	u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
>   	size_t aligned_size, align = epc_features->align;
> @@ -270,7 +276,32 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
>   	dma_addr_t phys_addr;
>   	struct pci_epc *epc;
>   	struct device *dev;
> -	void *space;
> +	void *space = NULL;
> +	dma_addr_t up;
> +
> +	up = inbound_addr + size - 1;
> +
> +	/*
> +	 *  Bits:            15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +	 *  Inbound_addr:    U  U  U  U  U  U  0 X X X X X X X X X
> +	 *  Up:              U  U  U  U  U  U  1 X X X X X X X X X
> +	 *
> +	 *  U means address bits have not change in Range [Inbound_Addr, Up]
> +	 *  X means bit 0 or 1.
> +	 *
> +	 *  Inbound_addr^Up  0  0  0  0  0  0  1 X X X X X X X X X
> +	 *  Find first bit 1 pos from MSB, 2 ^ pos windows will cover
> +	 *  [Inbound_Addr, Up] range.
> +	 */
> +	if (!from_memory) {
> +		int pos;
> +
> +		for (pos = sizeof(dma_addr_t) - 1; pos > 0; pos--)
> +			if ((up ^ inbound_addr) & BIT_ULL(pos))
> +				break;
> +

sizeof(dma_addr_t) returns bytes, not bits.
so 7..1 time loop in enough here ?

> +		size = 1 << pos;
> +	}
>   
>   	if (size < 128)
>   		size = 128;
> @@ -283,7 +314,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
>   		if (size > bar_fixed_size) {
>   			dev_err(&epf->dev,
>   				"requested BAR size is larger than fixed size\n");
> -			return NULL;
> +			return -EINVAL;
>   		}
>   		size = bar_fixed_size;
>   	} else {
> @@ -308,13 +339,25 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
>   	}
>   
>   	dev = epc->dev.parent;
> -	space = dma_alloc_coherent(dev, aligned_size, &phys_addr, GFP_KERNEL);
> -	if (!space) {
> -		dev_err(dev, "failed to allocate mem space\n");
> -		return NULL;
> +
> +	if (from_memory) {
> +		space = dma_alloc_coherent(dev, aligned_size,
> +					   &phys_addr, GFP_KERNEL);
> +		if (!space) {
> +			dev_err(dev, "failed to allocate mem space\n");
> +			return -ENOMEM;
> +		}
> +	}
> +
> +	epf_bar[bar].phys_addr = from_memory ?
> +			phys_addr : ALIGN_DOWN(inbound_addr, aligned_size);
> +
> +	if (!from_memory && (epf_bar[bar].phys_addr + size < up)) {
> +		dev_err(&epf->dev,
> +			"Given bar can't fit required inbound memory region\n");

consider bar -> BAR

> +		return -EINVAL;
>   	}
>   


Thanks,
Alok
Re: [PATCH 1/2] PCI: endpoint: Enhance pci_epf_alloc_space() and rename to pci_epf_set_inbound_space()
Posted by Frank Li 3 weeks ago
On Fri, Aug 29, 2025 at 10:51:56PM +0530, ALOK TIWARI wrote:
>
>
> On 8/16/2025 3:50 AM, Frank Li wrote:
> > +int pci_epf_set_inbound_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,
> > +			      bool from_memory,
> > +			      dma_addr_t inbound_addr)
> >   {
> >   	u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
> >   	size_t aligned_size, align = epc_features->align;
> > @@ -270,7 +276,32 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
> >   	dma_addr_t phys_addr;
> >   	struct pci_epc *epc;
> >   	struct device *dev;
> > -	void *space;
> > +	void *space = NULL;
> > +	dma_addr_t up;
> > +
> > +	up = inbound_addr + size - 1;
> > +
> > +	/*
> > +	 *  Bits:            15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> > +	 *  Inbound_addr:    U  U  U  U  U  U  0 X X X X X X X X X
> > +	 *  Up:              U  U  U  U  U  U  1 X X X X X X X X X
> > +	 *
> > +	 *  U means address bits have not change in Range [Inbound_Addr, Up]
> > +	 *  X means bit 0 or 1.
> > +	 *
> > +	 *  Inbound_addr^Up  0  0  0  0  0  0  1 X X X X X X X X X
> > +	 *  Find first bit 1 pos from MSB, 2 ^ pos windows will cover
> > +	 *  [Inbound_Addr, Up] range.
> > +	 */
> > +	if (!from_memory) {
> > +		int pos;
> > +
> > +		for (pos = sizeof(dma_addr_t) - 1; pos > 0; pos--)
> > +			if ((up ^ inbound_addr) & BIT_ULL(pos))
> > +				break;
> > +
>
> sizeof(dma_addr_t) returns bytes, not bits.
> so 7..1 time loop in enough here ?

good find.

Frank
>
> > +		size = 1 << pos;
> > +	}
> >   	if (size < 128)
> >   		size = 128;
> > @@ -283,7 +314,7 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
> >   		if (size > bar_fixed_size) {
> >   			dev_err(&epf->dev,
> >   				"requested BAR size is larger than fixed size\n");
> > -			return NULL;
> > +			return -EINVAL;
> >   		}
> >   		size = bar_fixed_size;
> >   	} else {
> > @@ -308,13 +339,25 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
> >   	}
> >   	dev = epc->dev.parent;
> > -	space = dma_alloc_coherent(dev, aligned_size, &phys_addr, GFP_KERNEL);
> > -	if (!space) {
> > -		dev_err(dev, "failed to allocate mem space\n");
> > -		return NULL;
> > +
> > +	if (from_memory) {
> > +		space = dma_alloc_coherent(dev, aligned_size,
> > +					   &phys_addr, GFP_KERNEL);
> > +		if (!space) {
> > +			dev_err(dev, "failed to allocate mem space\n");
> > +			return -ENOMEM;
> > +		}
> > +	}
> > +
> > +	epf_bar[bar].phys_addr = from_memory ?
> > +			phys_addr : ALIGN_DOWN(inbound_addr, aligned_size);
> > +
> > +	if (!from_memory && (epf_bar[bar].phys_addr + size < up)) {
> > +		dev_err(&epf->dev,
> > +			"Given bar can't fit required inbound memory region\n");
>
> consider bar -> BAR
>
> > +		return -EINVAL;
> >   	}
>
>
> Thanks,
> Alok