diff mbox series

[v3,1/6] PCI: endpoint: Add BAR type BAR_RESIZABLE

Message ID 20250113102730.1700963-9-cassel@kernel.org (mailing list archive)
State New
Delegated to: Krzysztof WilczyƄski
Headers show
Series PCI: endpoint: Add support for resizable BARs | expand

Commit Message

Niklas Cassel Jan. 13, 2025, 10:27 a.m. UTC
A resizable BAR is different from a normal BAR in a few ways:
-The minimum size of a resizable BAR is 1 MB.
-Each BAR that is resizable has a Capability and Control register in the
 Resizable BAR Capability structure.

These registers contain the supported sizes and the currently selected
size of a resizable BAR.

The supported sizes is a bitmap of the supported sizes. The selected size
is a single value that is equal to one of the supported sizes.

A resizable BAR thus has to be configured differently than a
BAR_PROGRAMMABLE BAR, which usually sets the BAR size/mask in a vendor
specific way.

The PCI endpoint framework currently does not support resizable BARs.

Add a BAR type BAR_RESIZABLE, so that an EPC driver can support resizable
BARs properly.

Note that the pci_epc_set_bar() API takes a struct pci_epf_bar which tells
the EPC driver how it wants to configure the BAR.

struct pci_epf_bar only has a single size struct member.

This means that an EPC driver will only be able to set a single supported
size. This is perfectly fine, as we do not need the complexity of allowing
a host to change the size of the BAR. If someone ever wants to support
resizing a resizable BAR, the pci_epc_set_bar() API can be extended in the
future.

With these changes, an EPC driver will be able to support resizable BARs
(we intentionally only support a single supported resizable BAR size).

Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/pci/endpoint/pci-epf-core.c | 4 ++++
 include/linux/pci-epc.h             | 3 +++
 2 files changed, 7 insertions(+)

Comments

Manivannan Sadhasivam Jan. 19, 2025, 5:14 a.m. UTC | #1
On Mon, Jan 13, 2025 at 11:27:32AM +0100, Niklas Cassel wrote:
> A resizable BAR is different from a normal BAR in a few ways:
> -The minimum size of a resizable BAR is 1 MB.
> -Each BAR that is resizable has a Capability and Control register in the
>  Resizable BAR Capability structure.
> 
> These registers contain the supported sizes and the currently selected
> size of a resizable BAR.
> 
> The supported sizes is a bitmap of the supported sizes. The selected size
> is a single value that is equal to one of the supported sizes.
> 
> A resizable BAR thus has to be configured differently than a
> BAR_PROGRAMMABLE BAR, which usually sets the BAR size/mask in a vendor
> specific way.
> 
> The PCI endpoint framework currently does not support resizable BARs.
> 
> Add a BAR type BAR_RESIZABLE, so that an EPC driver can support resizable
> BARs properly.
> 
> Note that the pci_epc_set_bar() API takes a struct pci_epf_bar which tells
> the EPC driver how it wants to configure the BAR.
> 
> struct pci_epf_bar only has a single size struct member.
> 
> This means that an EPC driver will only be able to set a single supported
> size. This is perfectly fine, as we do not need the complexity of allowing
> a host to change the size of the BAR. If someone ever wants to support
> resizing a resizable BAR, the pci_epc_set_bar() API can be extended in the
> future.
> 
> With these changes, an EPC driver will be able to support resizable BARs
> (we intentionally only support a single supported resizable BAR size).

Again, this is a bit of ambiguity. Even with these changes, an EPC driver
wouldn't be able to support resizable BARs which by the concept mean that the
host would be able to resize the BARs dynamically. Even though you are writing
the limitation in brackets, I think this sentence needs to be reworded.

> 
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
> ---
>  drivers/pci/endpoint/pci-epf-core.c | 4 ++++
>  include/linux/pci-epc.h             | 3 +++
>  2 files changed, 7 insertions(+)
> 
> diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
> index 50bc2892a36c..394395c7f8de 100644
> --- a/drivers/pci/endpoint/pci-epf-core.c
> +++ b/drivers/pci/endpoint/pci-epf-core.c
> @@ -274,6 +274,10 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
>  	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,
> diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
> index e818e3fdcded..e9d5ed23914f 100644
> --- a/include/linux/pci-epc.h
> +++ b/include/linux/pci-epc.h
> @@ -188,11 +188,14 @@ struct pci_epc {
>   * enum pci_epc_bar_type - configurability of endpoint BAR
>   * @BAR_PROGRAMMABLE: The BAR mask can be configured by the EPC.
>   * @BAR_FIXED: The BAR mask is fixed by the hardware.
> + * @BAR_RESIZABLE: The BAR implements the PCI-SIG Resizable BAR Capability.

> + *                 An EPC driver can currently only set a single supported size.

Could you please add 'NOTE' or 'TODO' so that this doesn't miss when a proper
resizable BAR functionality added later?

- Mani

>   * @BAR_RESERVED: The BAR should not be touched by an EPF driver.
>   */
>  enum pci_epc_bar_type {
>  	BAR_PROGRAMMABLE = 0,
>  	BAR_FIXED,
> +	BAR_RESIZABLE,
>  	BAR_RESERVED,
>  };
>  
> -- 
> 2.47.1
>
diff mbox series

Patch

diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index 50bc2892a36c..394395c7f8de 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -274,6 +274,10 @@  void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 	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,
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index e818e3fdcded..e9d5ed23914f 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -188,11 +188,14 @@  struct pci_epc {
  * enum pci_epc_bar_type - configurability of endpoint BAR
  * @BAR_PROGRAMMABLE: The BAR mask can be configured by the EPC.
  * @BAR_FIXED: The BAR mask is fixed by the hardware.
+ * @BAR_RESIZABLE: The BAR implements the PCI-SIG Resizable BAR Capability.
+ *                 An EPC driver can currently only set a single supported size.
  * @BAR_RESERVED: The BAR should not be touched by an EPF driver.
  */
 enum pci_epc_bar_type {
 	BAR_PROGRAMMABLE = 0,
 	BAR_FIXED,
+	BAR_RESIZABLE,
 	BAR_RESERVED,
 };