* [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
@ 2026-01-23 18:07 Niklas Cassel
2026-01-26 18:20 ` Frank Li
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Niklas Cassel @ 2026-01-23 18:07 UTC (permalink / raw)
To: Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Jonathan Corbet
Cc: Frank.Li, dlemoal, Koichiro Den, Niklas Cassel, linux-pci,
linux-doc
Add bar{0,1,2,3,4,5}_size attributes in configfs, so that the user is not
restricted to run pci-epf-test with the hardcoded BAR size values defined
in pci-epf-test.c.
This code is shamelessly more or less copy pasted from pci-epf-vntb.c
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
Documentation/PCI/endpoint/pci-test-howto.rst | 16 ++++
drivers/pci/endpoint/functions/pci-epf-test.c | 92 ++++++++++++++++++-
2 files changed, 106 insertions(+), 2 deletions(-)
diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst
index dd66858cde46..71975721cfd5 100644
--- a/Documentation/PCI/endpoint/pci-test-howto.rst
+++ b/Documentation/PCI/endpoint/pci-test-howto.rst
@@ -84,6 +84,22 @@ device, the following commands can be used::
# echo 32 > functions/pci_epf_test/func1/msi_interrupts
# echo 2048 > functions/pci_epf_test/func1/msix_interrupts
+By default, pci-epf-test uses the following BAR sizes::
+
+ # grep . functions/pci_epf_test/func1/pci_epf_test.0/bar?_size
+ functions/pci_epf_test/func1/pci_epf_test.0/bar0_size:512
+ functions/pci_epf_test/func1/pci_epf_test.0/bar1_size:512
+ functions/pci_epf_test/func1/pci_epf_test.0/bar2_size:1024
+ functions/pci_epf_test/func1/pci_epf_test.0/bar3_size:16384
+ functions/pci_epf_test/func1/pci_epf_test.0/bar4_size:131072
+ functions/pci_epf_test/func1/pci_epf_test.0/bar5_size:1048576
+
+The user can override a default value using e.g.::
+ # echo 1048576 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
+
+Note: Some endpoint controllers might have fixed size BARs, or reserved BARs,
+for such controllers, the corresponding BAR size in configfs will be ignored.
+
Binding pci-epf-test Device to EP Controller
--------------------------------------------
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index b785d488c284..fda257e46920 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -63,6 +63,7 @@ static struct workqueue_struct *kpcitest_workqueue;
struct pci_epf_test {
void *reg[PCI_STD_NUM_BARS];
struct pci_epf *epf;
+ struct config_group group;
enum pci_barno test_reg_bar;
size_t msix_table_offset;
struct delayed_work cmd_handler;
@@ -76,6 +77,7 @@ struct pci_epf_test {
bool dma_private;
const struct pci_epc_features *epc_features;
struct pci_epf_bar db_bar;
+ size_t bar_size[PCI_STD_NUM_BARS];
};
struct pci_epf_test_reg {
@@ -102,7 +104,8 @@ static struct pci_epf_header test_header = {
.interrupt_pin = PCI_INTERRUPT_INTA,
};
-static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
+/* default BAR sizes, can be overridden by the user using configfs */
+static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
static void pci_epf_test_dma_callback(void *param)
{
@@ -1070,7 +1073,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
if (epc_features->bar[bar].type == BAR_FIXED)
test_reg_size = epc_features->bar[bar].fixed_size;
else
- test_reg_size = bar_size[bar];
+ test_reg_size = epf_test->bar_size[bar];
base = pci_epf_alloc_space(epf, test_reg_size, bar,
epc_features, PRIMARY_INTERFACE);
@@ -1142,6 +1145,87 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
pci_epf_test_free_space(epf);
}
+#define PCI_EPF_TEST_BAR_SIZE_R(_name, _id) \
+ static ssize_t pci_epf_test_##_name##_show(struct config_item *item, \
+ char *page) \
+ { \
+ struct config_group *group = to_config_group(item); \
+ struct pci_epf_test *epf_test = container_of(group, \
+ struct pci_epf_test, group); \
+ \
+ return sprintf(page, "%zu\n", epf_test->bar_size[_id]); \
+ }
+
+#define PCI_EPF_TEST_BAR_SIZE_W(_name, _id) \
+ static ssize_t pci_epf_test_##_name##_store(struct config_item *item, \
+ const char *page, size_t len) \
+ { \
+ struct config_group *group = to_config_group(item); \
+ struct pci_epf_test *epf_test = container_of(group, \
+ struct pci_epf_test, group); \
+ int val; \
+ int ret; \
+ \
+ ret = kstrtouint(page, 0, &val); \
+ if (ret) \
+ return ret; \
+ \
+ if (!is_power_of_2(val)) \
+ return -EINVAL; \
+ \
+ epf_test->bar_size[_id] = val; \
+ \
+ return len; \
+ }
+
+PCI_EPF_TEST_BAR_SIZE_R(bar0_size, BAR_0)
+PCI_EPF_TEST_BAR_SIZE_W(bar0_size, BAR_0)
+PCI_EPF_TEST_BAR_SIZE_R(bar1_size, BAR_1)
+PCI_EPF_TEST_BAR_SIZE_W(bar1_size, BAR_1)
+PCI_EPF_TEST_BAR_SIZE_R(bar2_size, BAR_2)
+PCI_EPF_TEST_BAR_SIZE_W(bar2_size, BAR_2)
+PCI_EPF_TEST_BAR_SIZE_R(bar3_size, BAR_3)
+PCI_EPF_TEST_BAR_SIZE_W(bar3_size, BAR_3)
+PCI_EPF_TEST_BAR_SIZE_R(bar4_size, BAR_4)
+PCI_EPF_TEST_BAR_SIZE_W(bar4_size, BAR_4)
+PCI_EPF_TEST_BAR_SIZE_R(bar5_size, BAR_5)
+PCI_EPF_TEST_BAR_SIZE_W(bar5_size, BAR_5)
+
+CONFIGFS_ATTR(pci_epf_test_, bar0_size);
+CONFIGFS_ATTR(pci_epf_test_, bar1_size);
+CONFIGFS_ATTR(pci_epf_test_, bar2_size);
+CONFIGFS_ATTR(pci_epf_test_, bar3_size);
+CONFIGFS_ATTR(pci_epf_test_, bar4_size);
+CONFIGFS_ATTR(pci_epf_test_, bar5_size);
+
+static struct configfs_attribute *pci_epf_test_attrs[] = {
+ &pci_epf_test_attr_bar0_size,
+ &pci_epf_test_attr_bar1_size,
+ &pci_epf_test_attr_bar2_size,
+ &pci_epf_test_attr_bar3_size,
+ &pci_epf_test_attr_bar4_size,
+ &pci_epf_test_attr_bar5_size,
+ NULL,
+};
+
+static const struct config_item_type pci_epf_test_group_type = {
+ .ct_attrs = pci_epf_test_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *pci_epf_test_add_cfs(struct pci_epf *epf,
+ struct config_group *group)
+{
+ struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+ struct config_group *epf_group = &epf_test->group;
+ struct device *dev = &epf->dev;
+
+ config_group_init_type_name(epf_group, dev_name(dev),
+ &pci_epf_test_group_type);
+
+ return epf_group;
+}
+
static const struct pci_epf_device_id pci_epf_test_ids[] = {
{
.name = "pci_epf_test",
@@ -1154,6 +1238,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
{
struct pci_epf_test *epf_test;
struct device *dev = &epf->dev;
+ enum pci_barno bar;
epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
if (!epf_test)
@@ -1161,6 +1246,8 @@ static int pci_epf_test_probe(struct pci_epf *epf,
epf->header = &test_header;
epf_test->epf = epf;
+ for (bar = BAR_0; bar < PCI_STD_NUM_BARS; bar++)
+ epf_test->bar_size[bar] = default_bar_size[bar];
INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler);
@@ -1173,6 +1260,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
static const struct pci_epf_ops ops = {
.unbind = pci_epf_test_unbind,
.bind = pci_epf_test_bind,
+ .add_cfs = pci_epf_test_add_cfs,
};
static struct pci_epf_driver test_driver = {
base-commit: c0dbaab0524adbc90d693aa15ab84354dd71acb2
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-23 18:07 [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes Niklas Cassel
@ 2026-01-26 18:20 ` Frank Li
2026-01-27 3:44 ` Koichiro Den
2026-01-28 8:17 ` Manivannan Sadhasivam
2 siblings, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-01-26 18:20 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Jonathan Corbet, dlemoal,
Koichiro Den, linux-pci, linux-doc
On Fri, Jan 23, 2026 at 07:07:48PM +0100, Niklas Cassel wrote:
> Add bar{0,1,2,3,4,5}_size attributes in configfs, so that the user is not
> restricted to run pci-epf-test with the hardcoded BAR size values defined
> in pci-epf-test.c.
>
> This code is shamelessly more or less copy pasted from pci-epf-vntb.c
>
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
> Documentation/PCI/endpoint/pci-test-howto.rst | 16 ++++
> drivers/pci/endpoint/functions/pci-epf-test.c | 92 ++++++++++++++++++-
> 2 files changed, 106 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst
> index dd66858cde46..71975721cfd5 100644
> --- a/Documentation/PCI/endpoint/pci-test-howto.rst
> +++ b/Documentation/PCI/endpoint/pci-test-howto.rst
> @@ -84,6 +84,22 @@ device, the following commands can be used::
> # echo 32 > functions/pci_epf_test/func1/msi_interrupts
> # echo 2048 > functions/pci_epf_test/func1/msix_interrupts
>
> +By default, pci-epf-test uses the following BAR sizes::
> +
> + # grep . functions/pci_epf_test/func1/pci_epf_test.0/bar?_size
> + functions/pci_epf_test/func1/pci_epf_test.0/bar0_size:512
> + functions/pci_epf_test/func1/pci_epf_test.0/bar1_size:512
> + functions/pci_epf_test/func1/pci_epf_test.0/bar2_size:1024
> + functions/pci_epf_test/func1/pci_epf_test.0/bar3_size:16384
> + functions/pci_epf_test/func1/pci_epf_test.0/bar4_size:131072
> + functions/pci_epf_test/func1/pci_epf_test.0/bar5_size:1048576
> +
> +The user can override a default value using e.g.::
> + # echo 1048576 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
> +
> +Note: Some endpoint controllers might have fixed size BARs, or reserved BARs,
> +for such controllers, the corresponding BAR size in configfs will be ignored.
> +
>
> Binding pci-epf-test Device to EP Controller
> --------------------------------------------
> diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> index b785d488c284..fda257e46920 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> @@ -63,6 +63,7 @@ static struct workqueue_struct *kpcitest_workqueue;
> struct pci_epf_test {
> void *reg[PCI_STD_NUM_BARS];
> struct pci_epf *epf;
> + struct config_group group;
> enum pci_barno test_reg_bar;
> size_t msix_table_offset;
> struct delayed_work cmd_handler;
> @@ -76,6 +77,7 @@ struct pci_epf_test {
> bool dma_private;
> const struct pci_epc_features *epc_features;
> struct pci_epf_bar db_bar;
> + size_t bar_size[PCI_STD_NUM_BARS];
> };
>
> struct pci_epf_test_reg {
> @@ -102,7 +104,8 @@ static struct pci_epf_header test_header = {
> .interrupt_pin = PCI_INTERRUPT_INTA,
> };
>
> -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> +/* default BAR sizes, can be overridden by the user using configfs */
> +static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
>
> static void pci_epf_test_dma_callback(void *param)
> {
> @@ -1070,7 +1073,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
> if (epc_features->bar[bar].type == BAR_FIXED)
> test_reg_size = epc_features->bar[bar].fixed_size;
> else
> - test_reg_size = bar_size[bar];
> + test_reg_size = epf_test->bar_size[bar];
>
> base = pci_epf_alloc_space(epf, test_reg_size, bar,
> epc_features, PRIMARY_INTERFACE);
> @@ -1142,6 +1145,87 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
> pci_epf_test_free_space(epf);
> }
>
> +#define PCI_EPF_TEST_BAR_SIZE_R(_name, _id) \
> + static ssize_t pci_epf_test_##_name##_show(struct config_item *item, \
> + char *page) \
> + { \
> + struct config_group *group = to_config_group(item); \
> + struct pci_epf_test *epf_test = container_of(group, \
> + struct pci_epf_test, group); \
> + \
> + return sprintf(page, "%zu\n", epf_test->bar_size[_id]); \
> + }
> +
> +#define PCI_EPF_TEST_BAR_SIZE_W(_name, _id) \
> + static ssize_t pci_epf_test_##_name##_store(struct config_item *item, \
> + const char *page, size_t len) \
> + { \
> + struct config_group *group = to_config_group(item); \
> + struct pci_epf_test *epf_test = container_of(group, \
> + struct pci_epf_test, group); \
> + int val; \
> + int ret; \
> + \
> + ret = kstrtouint(page, 0, &val); \
> + if (ret) \
> + return ret; \
> + \
> + if (!is_power_of_2(val)) \
> + return -EINVAL; \
> + \
> + epf_test->bar_size[_id] = val; \
> + \
> + return len; \
> + }
> +
> +PCI_EPF_TEST_BAR_SIZE_R(bar0_size, BAR_0)
> +PCI_EPF_TEST_BAR_SIZE_W(bar0_size, BAR_0)
> +PCI_EPF_TEST_BAR_SIZE_R(bar1_size, BAR_1)
> +PCI_EPF_TEST_BAR_SIZE_W(bar1_size, BAR_1)
> +PCI_EPF_TEST_BAR_SIZE_R(bar2_size, BAR_2)
> +PCI_EPF_TEST_BAR_SIZE_W(bar2_size, BAR_2)
> +PCI_EPF_TEST_BAR_SIZE_R(bar3_size, BAR_3)
> +PCI_EPF_TEST_BAR_SIZE_W(bar3_size, BAR_3)
> +PCI_EPF_TEST_BAR_SIZE_R(bar4_size, BAR_4)
> +PCI_EPF_TEST_BAR_SIZE_W(bar4_size, BAR_4)
> +PCI_EPF_TEST_BAR_SIZE_R(bar5_size, BAR_5)
> +PCI_EPF_TEST_BAR_SIZE_W(bar5_size, BAR_5)
> +
> +CONFIGFS_ATTR(pci_epf_test_, bar0_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar1_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar2_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar3_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar4_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar5_size);
> +
> +static struct configfs_attribute *pci_epf_test_attrs[] = {
> + &pci_epf_test_attr_bar0_size,
> + &pci_epf_test_attr_bar1_size,
> + &pci_epf_test_attr_bar2_size,
> + &pci_epf_test_attr_bar3_size,
> + &pci_epf_test_attr_bar4_size,
> + &pci_epf_test_attr_bar5_size,
> + NULL,
> +};
> +
> +static const struct config_item_type pci_epf_test_group_type = {
> + .ct_attrs = pci_epf_test_attrs,
> + .ct_owner = THIS_MODULE,
> +};
> +
> +static struct config_group *pci_epf_test_add_cfs(struct pci_epf *epf,
> + struct config_group *group)
> +{
> + struct pci_epf_test *epf_test = epf_get_drvdata(epf);
> + struct config_group *epf_group = &epf_test->group;
> + struct device *dev = &epf->dev;
> +
> + config_group_init_type_name(epf_group, dev_name(dev),
> + &pci_epf_test_group_type);
> +
> + return epf_group;
> +}
> +
> static const struct pci_epf_device_id pci_epf_test_ids[] = {
> {
> .name = "pci_epf_test",
> @@ -1154,6 +1238,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> {
> struct pci_epf_test *epf_test;
> struct device *dev = &epf->dev;
> + enum pci_barno bar;
>
> epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
> if (!epf_test)
> @@ -1161,6 +1246,8 @@ static int pci_epf_test_probe(struct pci_epf *epf,
>
> epf->header = &test_header;
> epf_test->epf = epf;
> + for (bar = BAR_0; bar < PCI_STD_NUM_BARS; bar++)
> + epf_test->bar_size[bar] = default_bar_size[bar];
>
> INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler);
>
> @@ -1173,6 +1260,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> static const struct pci_epf_ops ops = {
> .unbind = pci_epf_test_unbind,
> .bind = pci_epf_test_bind,
> + .add_cfs = pci_epf_test_add_cfs,
> };
>
> static struct pci_epf_driver test_driver = {
>
> base-commit: c0dbaab0524adbc90d693aa15ab84354dd71acb2
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-23 18:07 [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes Niklas Cassel
2026-01-26 18:20 ` Frank Li
@ 2026-01-27 3:44 ` Koichiro Den
2026-01-27 9:47 ` Niklas Cassel
2026-01-28 8:17 ` Manivannan Sadhasivam
2 siblings, 1 reply; 8+ messages in thread
From: Koichiro Den @ 2026-01-27 3:44 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Jonathan Corbet, Frank.Li,
dlemoal, linux-pci, linux-doc
On Fri, Jan 23, 2026 at 07:07:48PM +0100, Niklas Cassel wrote:
> Add bar{0,1,2,3,4,5}_size attributes in configfs, so that the user is not
> restricted to run pci-epf-test with the hardcoded BAR size values defined
> in pci-epf-test.c.
>
> This code is shamelessly more or less copy pasted from pci-epf-vntb.c
>
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
This is useful, thanks!
I've used this patch as a dependency for my series [1], and it works fine.
Tested-by: Koichiro Den <den@valinux.co.jp>
[1] https://lore.kernel.org/linux-pci/20260124145012.2794108-1-den@valinux.co.jp/
> ---
> Documentation/PCI/endpoint/pci-test-howto.rst | 16 ++++
> drivers/pci/endpoint/functions/pci-epf-test.c | 92 ++++++++++++++++++-
> 2 files changed, 106 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst
> index dd66858cde46..71975721cfd5 100644
> --- a/Documentation/PCI/endpoint/pci-test-howto.rst
> +++ b/Documentation/PCI/endpoint/pci-test-howto.rst
> @@ -84,6 +84,22 @@ device, the following commands can be used::
> # echo 32 > functions/pci_epf_test/func1/msi_interrupts
> # echo 2048 > functions/pci_epf_test/func1/msix_interrupts
>
> +By default, pci-epf-test uses the following BAR sizes::
> +
> + # grep . functions/pci_epf_test/func1/pci_epf_test.0/bar?_size
> + functions/pci_epf_test/func1/pci_epf_test.0/bar0_size:512
> + functions/pci_epf_test/func1/pci_epf_test.0/bar1_size:512
> + functions/pci_epf_test/func1/pci_epf_test.0/bar2_size:1024
> + functions/pci_epf_test/func1/pci_epf_test.0/bar3_size:16384
> + functions/pci_epf_test/func1/pci_epf_test.0/bar4_size:131072
> + functions/pci_epf_test/func1/pci_epf_test.0/bar5_size:1048576
> +
> +The user can override a default value using e.g.::
> + # echo 1048576 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
> +
> +Note: Some endpoint controllers might have fixed size BARs, or reserved BARs,
> +for such controllers, the corresponding BAR size in configfs will be ignored.
> +
>
> Binding pci-epf-test Device to EP Controller
> --------------------------------------------
> diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> index b785d488c284..fda257e46920 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> @@ -63,6 +63,7 @@ static struct workqueue_struct *kpcitest_workqueue;
> struct pci_epf_test {
> void *reg[PCI_STD_NUM_BARS];
> struct pci_epf *epf;
> + struct config_group group;
> enum pci_barno test_reg_bar;
> size_t msix_table_offset;
> struct delayed_work cmd_handler;
> @@ -76,6 +77,7 @@ struct pci_epf_test {
> bool dma_private;
> const struct pci_epc_features *epc_features;
> struct pci_epf_bar db_bar;
> + size_t bar_size[PCI_STD_NUM_BARS];
> };
>
> struct pci_epf_test_reg {
> @@ -102,7 +104,8 @@ static struct pci_epf_header test_header = {
> .interrupt_pin = PCI_INTERRUPT_INTA,
> };
>
> -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> +/* default BAR sizes, can be overridden by the user using configfs */
> +static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
>
> static void pci_epf_test_dma_callback(void *param)
> {
> @@ -1070,7 +1073,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
> if (epc_features->bar[bar].type == BAR_FIXED)
> test_reg_size = epc_features->bar[bar].fixed_size;
> else
> - test_reg_size = bar_size[bar];
> + test_reg_size = epf_test->bar_size[bar];
>
> base = pci_epf_alloc_space(epf, test_reg_size, bar,
> epc_features, PRIMARY_INTERFACE);
> @@ -1142,6 +1145,87 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
> pci_epf_test_free_space(epf);
> }
>
> +#define PCI_EPF_TEST_BAR_SIZE_R(_name, _id) \
> + static ssize_t pci_epf_test_##_name##_show(struct config_item *item, \
> + char *page) \
> + { \
> + struct config_group *group = to_config_group(item); \
> + struct pci_epf_test *epf_test = container_of(group, \
> + struct pci_epf_test, group); \
> + \
> + return sprintf(page, "%zu\n", epf_test->bar_size[_id]); \
> + }
> +
> +#define PCI_EPF_TEST_BAR_SIZE_W(_name, _id) \
> + static ssize_t pci_epf_test_##_name##_store(struct config_item *item, \
> + const char *page, size_t len) \
> + { \
> + struct config_group *group = to_config_group(item); \
> + struct pci_epf_test *epf_test = container_of(group, \
> + struct pci_epf_test, group); \
> + int val; \
> + int ret; \
> + \
> + ret = kstrtouint(page, 0, &val); \
> + if (ret) \
> + return ret; \
> + \
> + if (!is_power_of_2(val)) \
> + return -EINVAL; \
> + \
> + epf_test->bar_size[_id] = val; \
> + \
> + return len; \
> + }
> +
> +PCI_EPF_TEST_BAR_SIZE_R(bar0_size, BAR_0)
> +PCI_EPF_TEST_BAR_SIZE_W(bar0_size, BAR_0)
> +PCI_EPF_TEST_BAR_SIZE_R(bar1_size, BAR_1)
> +PCI_EPF_TEST_BAR_SIZE_W(bar1_size, BAR_1)
> +PCI_EPF_TEST_BAR_SIZE_R(bar2_size, BAR_2)
> +PCI_EPF_TEST_BAR_SIZE_W(bar2_size, BAR_2)
> +PCI_EPF_TEST_BAR_SIZE_R(bar3_size, BAR_3)
> +PCI_EPF_TEST_BAR_SIZE_W(bar3_size, BAR_3)
> +PCI_EPF_TEST_BAR_SIZE_R(bar4_size, BAR_4)
> +PCI_EPF_TEST_BAR_SIZE_W(bar4_size, BAR_4)
> +PCI_EPF_TEST_BAR_SIZE_R(bar5_size, BAR_5)
> +PCI_EPF_TEST_BAR_SIZE_W(bar5_size, BAR_5)
> +
> +CONFIGFS_ATTR(pci_epf_test_, bar0_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar1_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar2_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar3_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar4_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar5_size);
> +
> +static struct configfs_attribute *pci_epf_test_attrs[] = {
> + &pci_epf_test_attr_bar0_size,
> + &pci_epf_test_attr_bar1_size,
> + &pci_epf_test_attr_bar2_size,
> + &pci_epf_test_attr_bar3_size,
> + &pci_epf_test_attr_bar4_size,
> + &pci_epf_test_attr_bar5_size,
> + NULL,
> +};
> +
> +static const struct config_item_type pci_epf_test_group_type = {
> + .ct_attrs = pci_epf_test_attrs,
> + .ct_owner = THIS_MODULE,
> +};
> +
> +static struct config_group *pci_epf_test_add_cfs(struct pci_epf *epf,
> + struct config_group *group)
> +{
> + struct pci_epf_test *epf_test = epf_get_drvdata(epf);
> + struct config_group *epf_group = &epf_test->group;
> + struct device *dev = &epf->dev;
> +
> + config_group_init_type_name(epf_group, dev_name(dev),
> + &pci_epf_test_group_type);
> +
> + return epf_group;
> +}
> +
> static const struct pci_epf_device_id pci_epf_test_ids[] = {
> {
> .name = "pci_epf_test",
> @@ -1154,6 +1238,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> {
> struct pci_epf_test *epf_test;
> struct device *dev = &epf->dev;
> + enum pci_barno bar;
>
> epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
> if (!epf_test)
> @@ -1161,6 +1246,8 @@ static int pci_epf_test_probe(struct pci_epf *epf,
>
> epf->header = &test_header;
> epf_test->epf = epf;
> + for (bar = BAR_0; bar < PCI_STD_NUM_BARS; bar++)
> + epf_test->bar_size[bar] = default_bar_size[bar];
>
> INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler);
>
> @@ -1173,6 +1260,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> static const struct pci_epf_ops ops = {
> .unbind = pci_epf_test_unbind,
> .bind = pci_epf_test_bind,
> + .add_cfs = pci_epf_test_add_cfs,
> };
>
> static struct pci_epf_driver test_driver = {
>
> base-commit: c0dbaab0524adbc90d693aa15ab84354dd71acb2
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-27 3:44 ` Koichiro Den
@ 2026-01-27 9:47 ` Niklas Cassel
2026-01-28 5:21 ` Koichiro Den
0 siblings, 1 reply; 8+ messages in thread
From: Niklas Cassel @ 2026-01-27 9:47 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Jonathan Corbet, Frank.Li,
dlemoal, linux-pci, linux-doc
On Tue, Jan 27, 2026 at 12:44:13PM +0900, Koichiro Den wrote:
> On Fri, Jan 23, 2026 at 07:07:48PM +0100, Niklas Cassel wrote:
> > Add bar{0,1,2,3,4,5}_size attributes in configfs, so that the user is not
> > restricted to run pci-epf-test with the hardcoded BAR size values defined
> > in pci-epf-test.c.
> >
> > This code is shamelessly more or less copy pasted from pci-epf-vntb.c
> >
> > Signed-off-by: Niklas Cassel <cassel@kernel.org>
>
> This is useful, thanks!
> I've used this patch as a dependency for my series [1], and it works fine.
>
> Tested-by: Koichiro Den <den@valinux.co.jp>
>
> [1] https://lore.kernel.org/linux-pci/20260124145012.2794108-1-den@valinux.co.jp/
Thank you for testing!
Just to clarify:
Your series is currently not depending on this patch, and neither do I think
that it should.
There will be a trivial conflict when PCI maintainers will try to merge them.
But the solution is to use your new values:
-static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
+static size_t bar_size[] = { 131072, 131072, 131072, 131072, 131072, 1048576 };
With my new variable name (default_bar_size):
-static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
+/* default BAR sizes, can be overridden by the user using configfs */
+static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
So AFAICT, it should a one line conflict resolution.
Since it is so trivial, it would be nice if the PCI maintainers could
handle that when applying, but I guess in worst case, one of us will
need to respin.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-27 9:47 ` Niklas Cassel
@ 2026-01-28 5:21 ` Koichiro Den
0 siblings, 0 replies; 8+ messages in thread
From: Koichiro Den @ 2026-01-28 5:21 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Jonathan Corbet, Frank.Li,
dlemoal, linux-pci, linux-doc
On Tue, Jan 27, 2026 at 10:47:52AM +0100, Niklas Cassel wrote:
> On Tue, Jan 27, 2026 at 12:44:13PM +0900, Koichiro Den wrote:
> > On Fri, Jan 23, 2026 at 07:07:48PM +0100, Niklas Cassel wrote:
> > > Add bar{0,1,2,3,4,5}_size attributes in configfs, so that the user is not
> > > restricted to run pci-epf-test with the hardcoded BAR size values defined
> > > in pci-epf-test.c.
> > >
> > > This code is shamelessly more or less copy pasted from pci-epf-vntb.c
> > >
> > > Signed-off-by: Niklas Cassel <cassel@kernel.org>
> >
> > This is useful, thanks!
> > I've used this patch as a dependency for my series [1], and it works fine.
> >
> > Tested-by: Koichiro Den <den@valinux.co.jp>
> >
> > [1] https://lore.kernel.org/linux-pci/20260124145012.2794108-1-den@valinux.co.jp/
>
>
> Thank you for testing!
>
> Just to clarify:
> Your series is currently not depending on this patch, and neither do I think
> that it should.
>
> There will be a trivial conflict when PCI maintainers will try to merge them.
>
> But the solution is to use your new values:
>
> -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> +static size_t bar_size[] = { 131072, 131072, 131072, 131072, 131072, 1048576 };
>
>
> With my new variable name (default_bar_size):
>
> -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> +/* default BAR sizes, can be overridden by the user using configfs */
> +static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
>
>
> So AFAICT, it should a one line conflict resolution.
>
> Since it is so trivial, it would be nice if the PCI maintainers could
> handle that when applying, but I guess in worst case, one of us will
> need to respin.
Yes, agreed, it's a trivial one-line conflict.
As for my series [1] v10, patches [6/8]-[8/8] (new test code) haven't
received any review feedback yet, so I suspect there's a good chance I'll
need to respin anyway. If I do a v11, I'll also resolve this conflict as
appropriate at that point. Even if it turns out no respin is needed for the
test code, I'll post v11 if the maitainers asks for resolving the conflict.
Kind regards,
Koichiro
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-23 18:07 [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes Niklas Cassel
2026-01-26 18:20 ` Frank Li
2026-01-27 3:44 ` Koichiro Den
@ 2026-01-28 8:17 ` Manivannan Sadhasivam
2026-01-28 16:35 ` Niklas Cassel
2 siblings, 1 reply; 8+ messages in thread
From: Manivannan Sadhasivam @ 2026-01-28 8:17 UTC (permalink / raw)
To: Niklas Cassel
Cc: Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
Jonathan Corbet, Frank.Li, dlemoal, Koichiro Den, linux-pci,
linux-doc
On Fri, Jan 23, 2026 at 07:07:48PM +0100, Niklas Cassel wrote:
> Add bar{0,1,2,3,4,5}_size attributes in configfs, so that the user is not
> restricted to run pci-epf-test with the hardcoded BAR size values defined
> in pci-epf-test.c.
>
> This code is shamelessly more or less copy pasted from pci-epf-vntb.c
>
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
> ---
> Documentation/PCI/endpoint/pci-test-howto.rst | 16 ++++
> drivers/pci/endpoint/functions/pci-epf-test.c | 92 ++++++++++++++++++-
> 2 files changed, 106 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst
> index dd66858cde46..71975721cfd5 100644
> --- a/Documentation/PCI/endpoint/pci-test-howto.rst
> +++ b/Documentation/PCI/endpoint/pci-test-howto.rst
> @@ -84,6 +84,22 @@ device, the following commands can be used::
> # echo 32 > functions/pci_epf_test/func1/msi_interrupts
> # echo 2048 > functions/pci_epf_test/func1/msix_interrupts
>
> +By default, pci-epf-test uses the following BAR sizes::
> +
> + # grep . functions/pci_epf_test/func1/pci_epf_test.0/bar?_size
> + functions/pci_epf_test/func1/pci_epf_test.0/bar0_size:512
> + functions/pci_epf_test/func1/pci_epf_test.0/bar1_size:512
> + functions/pci_epf_test/func1/pci_epf_test.0/bar2_size:1024
> + functions/pci_epf_test/func1/pci_epf_test.0/bar3_size:16384
> + functions/pci_epf_test/func1/pci_epf_test.0/bar4_size:131072
> + functions/pci_epf_test/func1/pci_epf_test.0/bar5_size:1048576
> +
> +The user can override a default value using e.g.::
> + # echo 1048576 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
> +
> +Note: Some endpoint controllers might have fixed size BARs, or reserved BARs,
> +for such controllers, the corresponding BAR size in configfs will be ignored.
> +
Silently ignoring the BAR size would create confusion. We should error out with
-EOPNOTSUPP if the BAR is a fixed size BAR.
>
> Binding pci-epf-test Device to EP Controller
> --------------------------------------------
> diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> index b785d488c284..fda257e46920 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> @@ -63,6 +63,7 @@ static struct workqueue_struct *kpcitest_workqueue;
> struct pci_epf_test {
> void *reg[PCI_STD_NUM_BARS];
> struct pci_epf *epf;
> + struct config_group group;
> enum pci_barno test_reg_bar;
> size_t msix_table_offset;
> struct delayed_work cmd_handler;
> @@ -76,6 +77,7 @@ struct pci_epf_test {
> bool dma_private;
> const struct pci_epc_features *epc_features;
> struct pci_epf_bar db_bar;
> + size_t bar_size[PCI_STD_NUM_BARS];
> };
>
> struct pci_epf_test_reg {
> @@ -102,7 +104,8 @@ static struct pci_epf_header test_header = {
> .interrupt_pin = PCI_INTERRUPT_INTA,
> };
>
> -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> +/* default BAR sizes, can be overridden by the user using configfs */
> +static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
>
> static void pci_epf_test_dma_callback(void *param)
> {
> @@ -1070,7 +1073,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
> if (epc_features->bar[bar].type == BAR_FIXED)
> test_reg_size = epc_features->bar[bar].fixed_size;
> else
> - test_reg_size = bar_size[bar];
> + test_reg_size = epf_test->bar_size[bar];
>
> base = pci_epf_alloc_space(epf, test_reg_size, bar,
> epc_features, PRIMARY_INTERFACE);
> @@ -1142,6 +1145,87 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
> pci_epf_test_free_space(epf);
> }
>
> +#define PCI_EPF_TEST_BAR_SIZE_R(_name, _id) \
> + static ssize_t pci_epf_test_##_name##_show(struct config_item *item, \
> + char *page) \
> + { \
> + struct config_group *group = to_config_group(item); \
> + struct pci_epf_test *epf_test = container_of(group, \
> + struct pci_epf_test, group); \
> + \
> + return sprintf(page, "%zu\n", epf_test->bar_size[_id]); \
> + }
> +
> +#define PCI_EPF_TEST_BAR_SIZE_W(_name, _id) \
> + static ssize_t pci_epf_test_##_name##_store(struct config_item *item, \
> + const char *page, size_t len) \
> + { \
> + struct config_group *group = to_config_group(item); \
> + struct pci_epf_test *epf_test = container_of(group, \
> + struct pci_epf_test, group); \
> + int val; \
> + int ret; \
> + \
> + ret = kstrtouint(page, 0, &val); \
> + if (ret) \
> + return ret; \
> + \
> + if (!is_power_of_2(val)) \
> + return -EINVAL; \
> + \
> + epf_test->bar_size[_id] = val; \
> + \
> + return len; \
> + }
> +
> +PCI_EPF_TEST_BAR_SIZE_R(bar0_size, BAR_0)
> +PCI_EPF_TEST_BAR_SIZE_W(bar0_size, BAR_0)
> +PCI_EPF_TEST_BAR_SIZE_R(bar1_size, BAR_1)
> +PCI_EPF_TEST_BAR_SIZE_W(bar1_size, BAR_1)
> +PCI_EPF_TEST_BAR_SIZE_R(bar2_size, BAR_2)
> +PCI_EPF_TEST_BAR_SIZE_W(bar2_size, BAR_2)
> +PCI_EPF_TEST_BAR_SIZE_R(bar3_size, BAR_3)
> +PCI_EPF_TEST_BAR_SIZE_W(bar3_size, BAR_3)
> +PCI_EPF_TEST_BAR_SIZE_R(bar4_size, BAR_4)
> +PCI_EPF_TEST_BAR_SIZE_W(bar4_size, BAR_4)
> +PCI_EPF_TEST_BAR_SIZE_R(bar5_size, BAR_5)
> +PCI_EPF_TEST_BAR_SIZE_W(bar5_size, BAR_5)
> +
> +CONFIGFS_ATTR(pci_epf_test_, bar0_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar1_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar2_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar3_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar4_size);
> +CONFIGFS_ATTR(pci_epf_test_, bar5_size);
> +
> +static struct configfs_attribute *pci_epf_test_attrs[] = {
> + &pci_epf_test_attr_bar0_size,
> + &pci_epf_test_attr_bar1_size,
> + &pci_epf_test_attr_bar2_size,
> + &pci_epf_test_attr_bar3_size,
> + &pci_epf_test_attr_bar4_size,
> + &pci_epf_test_attr_bar5_size,
> + NULL,
> +};
> +
> +static const struct config_item_type pci_epf_test_group_type = {
> + .ct_attrs = pci_epf_test_attrs,
> + .ct_owner = THIS_MODULE,
> +};
> +
> +static struct config_group *pci_epf_test_add_cfs(struct pci_epf *epf,
> + struct config_group *group)
> +{
> + struct pci_epf_test *epf_test = epf_get_drvdata(epf);
> + struct config_group *epf_group = &epf_test->group;
> + struct device *dev = &epf->dev;
> +
> + config_group_init_type_name(epf_group, dev_name(dev),
> + &pci_epf_test_group_type);
> +
> + return epf_group;
> +}
> +
> static const struct pci_epf_device_id pci_epf_test_ids[] = {
> {
> .name = "pci_epf_test",
> @@ -1154,6 +1238,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> {
> struct pci_epf_test *epf_test;
> struct device *dev = &epf->dev;
> + enum pci_barno bar;
>
> epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
> if (!epf_test)
> @@ -1161,6 +1246,8 @@ static int pci_epf_test_probe(struct pci_epf *epf,
>
> epf->header = &test_header;
> epf_test->epf = epf;
> + for (bar = BAR_0; bar < PCI_STD_NUM_BARS; bar++)
> + epf_test->bar_size[bar] = default_bar_size[bar];
>
It'd be more clean if 'epf_test->bar_size[bar]' always holds the actual BAR size
i.e., one of default/user configured/fixed size. This will allow us to print the
actual BAR size used for testing. For this, the initial size setting should
happen in pci_epf_test_bind().
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-28 8:17 ` Manivannan Sadhasivam
@ 2026-01-28 16:35 ` Niklas Cassel
2026-01-28 18:59 ` Niklas Cassel
0 siblings, 1 reply; 8+ messages in thread
From: Niklas Cassel @ 2026-01-28 16:35 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
Jonathan Corbet, Frank.Li, dlemoal, Koichiro Den, linux-pci,
linux-doc
Hello Mani,
On Wed, Jan 28, 2026 at 01:47:45PM +0530, Manivannan Sadhasivam wrote:
> > +
> > + # grep . functions/pci_epf_test/func1/pci_epf_test.0/bar?_size
> > + functions/pci_epf_test/func1/pci_epf_test.0/bar0_size:512
> > + functions/pci_epf_test/func1/pci_epf_test.0/bar1_size:512
> > + functions/pci_epf_test/func1/pci_epf_test.0/bar2_size:1024
> > + functions/pci_epf_test/func1/pci_epf_test.0/bar3_size:16384
> > + functions/pci_epf_test/func1/pci_epf_test.0/bar4_size:131072
> > + functions/pci_epf_test/func1/pci_epf_test.0/bar5_size:1048576
> > +
> > +The user can override a default value using e.g.::
> > + # echo 1048576 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
> > +
> > +Note: Some endpoint controllers might have fixed size BARs, or reserved BARs,
> > +for such controllers, the corresponding BAR size in configfs will be ignored.
> > +
>
> Silently ignoring the BAR size would create confusion. We should error out with
> -EOPNOTSUPP if the BAR is a fixed size BAR.
My initial idea was indeed to return -EOPNOTSUPP if the BAR is a fixed size BAR.
The problem however is that the information if a BAR is FIXED or not is in
epf->epc->features. epf->epc is NULL until the EPF has been bound to an EPC via
configfs.
>
> >
> > Binding pci-epf-test Device to EP Controller
> > --------------------------------------------
> > diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> > index b785d488c284..fda257e46920 100644
> > --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> > +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> > @@ -63,6 +63,7 @@ static struct workqueue_struct *kpcitest_workqueue;
> > struct pci_epf_test {
> > void *reg[PCI_STD_NUM_BARS];
> > struct pci_epf *epf;
> > + struct config_group group;
> > enum pci_barno test_reg_bar;
> > size_t msix_table_offset;
> > struct delayed_work cmd_handler;
> > @@ -76,6 +77,7 @@ struct pci_epf_test {
> > bool dma_private;
> > const struct pci_epc_features *epc_features;
> > struct pci_epf_bar db_bar;
> > + size_t bar_size[PCI_STD_NUM_BARS];
> > };
> >
> > struct pci_epf_test_reg {
> > @@ -102,7 +104,8 @@ static struct pci_epf_header test_header = {
> > .interrupt_pin = PCI_INTERRUPT_INTA,
> > };
> >
> > -static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> > +/* default BAR sizes, can be overridden by the user using configfs */
> > +static size_t default_bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> >
> > static void pci_epf_test_dma_callback(void *param)
> > {
> > @@ -1070,7 +1073,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
> > if (epc_features->bar[bar].type == BAR_FIXED)
> > test_reg_size = epc_features->bar[bar].fixed_size;
> > else
> > - test_reg_size = bar_size[bar];
> > + test_reg_size = epf_test->bar_size[bar];
> >
> > base = pci_epf_alloc_space(epf, test_reg_size, bar,
> > epc_features, PRIMARY_INTERFACE);
> > @@ -1142,6 +1145,87 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
> > pci_epf_test_free_space(epf);
> > }
> >
> > +#define PCI_EPF_TEST_BAR_SIZE_R(_name, _id) \
> > + static ssize_t pci_epf_test_##_name##_show(struct config_item *item, \
> > + char *page) \
> > + { \
> > + struct config_group *group = to_config_group(item); \
> > + struct pci_epf_test *epf_test = container_of(group, \
> > + struct pci_epf_test, group); \
> > + \
> > + return sprintf(page, "%zu\n", epf_test->bar_size[_id]); \
> > + }
> > +
> > +#define PCI_EPF_TEST_BAR_SIZE_W(_name, _id) \
> > + static ssize_t pci_epf_test_##_name##_store(struct config_item *item, \
> > + const char *page, size_t len) \
> > + { \
> > + struct config_group *group = to_config_group(item); \
> > + struct pci_epf_test *epf_test = container_of(group, \
> > + struct pci_epf_test, group); \
> > + int val; \
> > + int ret; \
> > + \
> > + ret = kstrtouint(page, 0, &val); \
> > + if (ret) \
> > + return ret; \
> > + \
> > + if (!is_power_of_2(val)) \
> > + return -EINVAL; \
> > + \
> > + epf_test->bar_size[_id] = val; \
> > + \
> > + return len; \
> > + }
> > +
> > +PCI_EPF_TEST_BAR_SIZE_R(bar0_size, BAR_0)
> > +PCI_EPF_TEST_BAR_SIZE_W(bar0_size, BAR_0)
> > +PCI_EPF_TEST_BAR_SIZE_R(bar1_size, BAR_1)
> > +PCI_EPF_TEST_BAR_SIZE_W(bar1_size, BAR_1)
> > +PCI_EPF_TEST_BAR_SIZE_R(bar2_size, BAR_2)
> > +PCI_EPF_TEST_BAR_SIZE_W(bar2_size, BAR_2)
> > +PCI_EPF_TEST_BAR_SIZE_R(bar3_size, BAR_3)
> > +PCI_EPF_TEST_BAR_SIZE_W(bar3_size, BAR_3)
> > +PCI_EPF_TEST_BAR_SIZE_R(bar4_size, BAR_4)
> > +PCI_EPF_TEST_BAR_SIZE_W(bar4_size, BAR_4)
> > +PCI_EPF_TEST_BAR_SIZE_R(bar5_size, BAR_5)
> > +PCI_EPF_TEST_BAR_SIZE_W(bar5_size, BAR_5)
> > +
> > +CONFIGFS_ATTR(pci_epf_test_, bar0_size);
> > +CONFIGFS_ATTR(pci_epf_test_, bar1_size);
> > +CONFIGFS_ATTR(pci_epf_test_, bar2_size);
> > +CONFIGFS_ATTR(pci_epf_test_, bar3_size);
> > +CONFIGFS_ATTR(pci_epf_test_, bar4_size);
> > +CONFIGFS_ATTR(pci_epf_test_, bar5_size);
> > +
> > +static struct configfs_attribute *pci_epf_test_attrs[] = {
> > + &pci_epf_test_attr_bar0_size,
> > + &pci_epf_test_attr_bar1_size,
> > + &pci_epf_test_attr_bar2_size,
> > + &pci_epf_test_attr_bar3_size,
> > + &pci_epf_test_attr_bar4_size,
> > + &pci_epf_test_attr_bar5_size,
> > + NULL,
> > +};
> > +
> > +static const struct config_item_type pci_epf_test_group_type = {
> > + .ct_attrs = pci_epf_test_attrs,
> > + .ct_owner = THIS_MODULE,
> > +};
> > +
> > +static struct config_group *pci_epf_test_add_cfs(struct pci_epf *epf,
> > + struct config_group *group)
> > +{
> > + struct pci_epf_test *epf_test = epf_get_drvdata(epf);
> > + struct config_group *epf_group = &epf_test->group;
> > + struct device *dev = &epf->dev;
> > +
> > + config_group_init_type_name(epf_group, dev_name(dev),
> > + &pci_epf_test_group_type);
> > +
> > + return epf_group;
> > +}
> > +
> > static const struct pci_epf_device_id pci_epf_test_ids[] = {
> > {
> > .name = "pci_epf_test",
> > @@ -1154,6 +1238,7 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> > {
> > struct pci_epf_test *epf_test;
> > struct device *dev = &epf->dev;
> > + enum pci_barno bar;
> >
> > epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
> > if (!epf_test)
> > @@ -1161,6 +1246,8 @@ static int pci_epf_test_probe(struct pci_epf *epf,
> >
> > epf->header = &test_header;
> > epf_test->epf = epf;
> > + for (bar = BAR_0; bar < PCI_STD_NUM_BARS; bar++)
> > + epf_test->bar_size[bar] = default_bar_size[bar];
> >
>
> It'd be more clean if 'epf_test->bar_size[bar]' always holds the actual BAR size
> i.e., one of default/user configured/fixed size. This will allow us to print the
> actual BAR size used for testing. For this, the initial size setting should
> happen in pci_epf_test_bind().
# mkdir functions/pci_epf_test/func1
will cause pci_epf_test_probe() to be called.
At this point, when the EPF has been created, but not bound to an EPC,
the user could still do:
# grep . functions/pci_epf_test/func1/pci_epf_test.0/bar?_size
If we want this to show something other than e.g. size 0 for all BAR
before binding to and EPC, then we thus need to initialize it in probe().
If you are happy with showing sizes as zero, and that the configfs writes
that a user made to bar*_size before binding to a EPC will be overwritten
(I guess we could also return -EINVAL if bar*_size is written before an EPC
has been bound to the EPF), the next problem is that:
# ln -s functions/pci_epf_test/func1 controllers/a40000000.pcie-ep/
[ 578.073152] pci_epf_test_bind
[ 578.075614] pci_epf_test_epc_init
will cause both pci_epf_test_bind and pci_epf_test_epc_init to be called.
(for all platforms expect those that can only work with external reference
clock).
As you know, pci_epf_test_epc_init() will call set_bar().
So, the suggestion in this patch is the most pragmatic way I could think of.
The only better solution would be to move all the set_bar() code (and probably
all code) from pci_epf_test_epc_init() to
# echo 1 > controllers/a40000000.pcie-ep/start
time.
But AFAICT, we do not have any callback in an EPF driver that gets called
before the link is started.
I guess we could theoretically add a new EPF callback which pci-epc-core.c
calls for each EPF driver, before calling epc->ops->start(epc); :
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 068155819c57..dc717c5fd195 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -180,6 +180,7 @@ EXPORT_SYMBOL_GPL(pci_epc_stop);
*/
int pci_epc_start(struct pci_epc *epc)
{
+ struct pci_epf *epf;
int ret;
if (IS_ERR(epc))
@@ -188,6 +189,14 @@ int pci_epc_start(struct pci_epc *epc)
if (!epc->ops->start)
return 0;
+ mutex_lock(&epc->list_lock);
+ list_for_each_entry(epf, &epc->pci_epf, list) {
+ mutex_lock(&epf->lock);
+ if (epf->event_ops && epf->event_ops->epc_start_link)
+ epf->event_ops->epc_start_link(epf);
+ mutex_unlock(&epf->lock);
+ }
+
mutex_lock(&epc->lock);
ret = epc->ops->start(epc);
mutex_unlock(&epc->lock);
I guess it should work.
But I am slightly worried of the complexity it brings...
Because we already have an .epc_init callback in an EPF driver.
If we also bring add a ".pre_start_link" callback in an EPF driver,
how should an EPF driver developer know what to put in each callback?
I guess in that case we would want to remove the .epc_init callback?
(Because calling .set_bar() etc. should work to be called in a
.pre_start_link for both those driver relying on external refclock and
for those that don't.
If you do
# echo 1 > controllers/a40000000.pcie-ep/start
on a platform that requires an external reflock, before the external
refclock is available, that is your own fault.
I guess we could detect that and give a nice error.)
Kind regards,
Niklas
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes
2026-01-28 16:35 ` Niklas Cassel
@ 2026-01-28 18:59 ` Niklas Cassel
0 siblings, 0 replies; 8+ messages in thread
From: Niklas Cassel @ 2026-01-28 18:59 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
Jonathan Corbet, Frank.Li, dlemoal, Koichiro Den, linux-pci,
linux-doc
On Wed, Jan 28, 2026 at 05:35:15PM +0100, Niklas Cassel wrote:
> On Wed, Jan 28, 2026 at 01:47:45PM +0530, Manivannan Sadhasivam wrote:
(snip)
> But I am slightly worried of the complexity it brings...
> Because we already have an .epc_init callback in an EPF driver.
> If we also bring add a ".pre_start_link" callback in an EPF driver,
> how should an EPF driver developer know what to put in each callback?
>
> I guess in that case we would want to remove the .epc_init callback?
>
> (Because calling .set_bar() etc. should work to be called in a
> .pre_start_link for both those driver relying on external refclock and
> for those that don't.
>
> If you do
> # echo 1 > controllers/a40000000.pcie-ep/start
> on a platform that requires an external reflock, before the external
> refclock is available, that is your own fault.
>
> I guess we could detect that and give a nice error.)
pci_epf_test_alloc_space() is called by pci_epf_test_bind().
pci_epc_set_bar() is called by pci_epf_test_epc_init().
On platforms that do not require an external reference clock to do
register writes to their own config space, i.e. all drivers except
(pcie-qcom and pcie-tegra194), a single configfs link command will cause
both both of these callback to be called directly after each other:
# ln -s functions/pci_epf_test/func1 controllers/a40000000.pcie-ep/
[ 578.073152] pci_epf_test_bind
[ 578.075614] pci_epf_test_epc_init
So, unless we want to change the design of pci-epf-test to:
1) Move the allocation of BARs from .bind() to a new
.pre_start_link() callback.
2) Move the call to pci_epc_set_bar() from epc_init() to a new
.pre_start_link() callback.
3) Remove the now unused .epc_init() callback.
...and for consistency, we would also need to do these steps for all
the other existing EPF drivers...
I am not convinced that it is worth reworking the EPF callbacks for this
(test driver) feature, which will only used for PCI endpoint developers,
especially given the complexity it would require.
For platforms drivers that require external reference clock, is it possible
to call
echo 1 > start
before we get refclock?
If so the design would probably need to be changed even more drastically...
When we introduce .epc_init, one of the reasons why we decided to have
alloc_space() and set_bar() in two different callbacks, was if a host driver
toggled PERST, the EPF driver would not need to call free() on the backing
memory it has allocated, e.g. I can see that pci_epf_test_epc_deinit() calls
clear_bar(), but the only place that actually frees the memory backing the
BARs is pci_epf_test_unbind().
What if the user wants to do:
# echo 1024 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
# echo 0 > controllers/a40000000.pcie-ep/start
# echo 2048 > functions/pci_epf_test/func1/pci_epf_test.0/bar1_size
# echo 1 > controllers/a40000000.pcie-ep/start
Do we want to make the allocation each time we echo 1 > start... ?
If someone stops the link.. is it really wrong to free the memory?
I'm not against this design, but with the complexity that we want
.epc_init() to only call set_bar(), and we probably want .pre_start_link()
to call alloc_space()...
I don't think that the small feature in this patch is enough
justification to modify how all EPF driver to their backing memory
allocations just for this...
Instead I will just send a new version such that if the user get -EINVAL
if trying to change bar*_size in configfs AFTER the EPF has been bound to
an EPC (i.e. it can only be done before binding to an EPC.), as that seems
like the most pragmatic compromise that will avoid (another) redesign of
the EPF callbacks.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-01-28 18:59 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-23 18:07 [PATCH] PCI: endpoint: pci-epf-test: Allow overriding default BAR sizes Niklas Cassel
2026-01-26 18:20 ` Frank Li
2026-01-27 3:44 ` Koichiro Den
2026-01-27 9:47 ` Niklas Cassel
2026-01-28 5:21 ` Koichiro Den
2026-01-28 8:17 ` Manivannan Sadhasivam
2026-01-28 16:35 ` Niklas Cassel
2026-01-28 18:59 ` Niklas Cassel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox