[PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API

Koichiro Den posted 11 patches 5 days, 6 hours ago
There is a newer version of this series
[PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
Posted by Koichiro Den 5 days, 6 hours ago
Add a new pci-epf-test command that exercises the newly added EPC API
pci_epc_get_remote_resources().

The test is intentionally a smoke test. It verifies that the API either
returns -EOPNOTSUPP or a well-formed resource list (non-zero phys/size
and known resource types). The result is reported to the host via a
status bit and an interrupt, consistent with existing pci-epf-test
commands.

Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
 drivers/pci/endpoint/functions/pci-epf-test.c | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 6952ee418622..6446a0a23865 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -35,6 +35,7 @@
 #define COMMAND_DISABLE_DOORBELL	BIT(7)
 #define COMMAND_BAR_SUBRANGE_SETUP	BIT(8)
 #define COMMAND_BAR_SUBRANGE_CLEAR	BIT(9)
+#define COMMAND_EPC_API			BIT(10)
 
 #define STATUS_READ_SUCCESS		BIT(0)
 #define STATUS_READ_FAIL		BIT(1)
@@ -54,6 +55,8 @@
 #define STATUS_BAR_SUBRANGE_SETUP_FAIL		BIT(15)
 #define STATUS_BAR_SUBRANGE_CLEAR_SUCCESS	BIT(16)
 #define STATUS_BAR_SUBRANGE_CLEAR_FAIL		BIT(17)
+#define STATUS_EPC_API_SUCCESS		BIT(18)
+#define STATUS_EPC_API_FAIL		BIT(19)
 
 #define FLAG_USE_DMA			BIT(0)
 
@@ -967,6 +970,87 @@ static void pci_epf_test_bar_subrange_clear(struct pci_epf_test *epf_test,
 	reg->status = cpu_to_le32(status);
 }
 
+static void pci_epf_test_epc_api(struct pci_epf_test *epf_test,
+				 struct pci_epf_test_reg *reg)
+{
+	struct pci_epc_remote_resource *resources = NULL;
+	u32 status = le32_to_cpu(reg->status);
+	struct pci_epf *epf = epf_test->epf;
+	struct device *dev = &epf->dev;
+	struct pci_epc *epc = epf->epc;
+	int num_resources;
+	int ret, i;
+
+	num_resources = pci_epc_get_remote_resources(epc, epf->func_no,
+						     epf->vfunc_no, NULL, 0);
+	if (num_resources == -EOPNOTSUPP || num_resources == 0)
+		goto out_success;
+	if (num_resources < 0)
+		goto err;
+
+	resources = kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);
+	if (!resources)
+		goto err;
+
+	ret = pci_epc_get_remote_resources(epc, epf->func_no, epf->vfunc_no,
+					   resources, num_resources);
+	if (ret < 0) {
+		dev_err(dev, "EPC remote resource query failed: %d\n", ret);
+		goto err_free;
+	}
+	if (ret > num_resources) {
+		dev_err(dev, "EPC API returned %d resources (max %d)\n",
+			ret, num_resources);
+		goto err_free;
+	}
+
+	for (i = 0; i < ret; i++) {
+		struct pci_epc_remote_resource *res = &resources[i];
+
+		if (!res->phys_addr || !res->size) {
+			dev_err(dev,
+				"Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
+				i, res->type, &res->phys_addr, res->size);
+			goto err_free;
+		}
+
+		/* Guard against address overflow */
+		if (res->phys_addr + res->size < res->phys_addr) {
+			dev_err(dev,
+				"Remote resource[%d] overflow (phys=%pa size=%llu)\n",
+				i, &res->phys_addr, res->size);
+			goto err_free;
+		}
+
+		switch (res->type) {
+		case PCI_EPC_RR_DMA_CTRL_MMIO:
+			/* Generic checks above are sufficient. */
+			break;
+		case PCI_EPC_RR_DMA_CHAN_DESC:
+			/*
+			 * hw_chan_id and ep2rc are informational. No extra validation
+			 * beyond the generic checks above is needed.
+			 */
+			break;
+		default:
+			dev_err(dev, "Unknown remote resource type %d\n", res->type);
+			goto err_free;
+		}
+	}
+
+out_success:
+	kfree(resources);
+	status |= STATUS_EPC_API_SUCCESS;
+	reg->status = cpu_to_le32(status);
+	return;
+
+err_free:
+	kfree(resources);
+err:
+	status |= STATUS_EPC_API_FAIL;
+	reg->status = cpu_to_le32(status);
+}
+
 static void pci_epf_test_cmd_handler(struct work_struct *work)
 {
 	u32 command;
@@ -1030,6 +1114,10 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
 		pci_epf_test_bar_subrange_clear(epf_test, reg);
 		pci_epf_test_raise_irq(epf_test, reg);
 		break;
+	case COMMAND_EPC_API:
+		pci_epf_test_epc_api(epf_test, reg);
+		pci_epf_test_raise_irq(epf_test, reg);
+		break;
 	default:
 		dev_err(dev, "Invalid command 0x%x\n", command);
 		break;
-- 
2.51.0
Re: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
Posted by kernel test robot 4 days, 19 hours ago
Hi Koichiro,

kernel test robot noticed the following build warnings:

[auto build test WARNING on pci/next]
[also build test WARNING on next-20260204]
[cannot apply to vkoul-dmaengine/next pci/for-linus linus/master v6.19-rc8]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Koichiro-Den/dmaengine-Add-hw_id-to-dma_slave_caps/20260204-230604
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next
patch link:    https://lore.kernel.org/r/20260204145440.950609-10-den%40valinux.co.jp
patch subject: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
config: um-randconfig-001-20260205 (https://download.01.org/0day-ci/archive/20260205/202602051059.2bwjcYJE-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9b8addffa70cee5b2acc5454712d9cf78ce45710)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260205/202602051059.2bwjcYJE-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602051059.2bwjcYJE-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/pci/endpoint/functions/pci-epf-test.c:11:
   In file included from include/linux/dmaengine.h:12:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:1209:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
    1209 |         return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
         |                                                   ~~~~~~~~~~ ^
>> drivers/pci/endpoint/functions/pci-epf-test.c:1013:36: warning: format specifies type 'unsigned long long' but the argument has type 'resource_size_t' (aka 'unsigned int') [-Wformat]
    1012 |                                 "Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
         |                                                                                     ~~~~
         |                                                                                     %u
    1013 |                                 i, res->type, &res->phys_addr, res->size);
         |                                                                ^~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   drivers/pci/endpoint/functions/pci-epf-test.c:1021:25: warning: format specifies type 'unsigned long long' but the argument has type 'resource_size_t' (aka 'unsigned int') [-Wformat]
    1020 |                                 "Remote resource[%d] overflow (phys=%pa size=%llu)\n",
         |                                                                              ~~~~
         |                                                                              %u
    1021 |                                 i, &res->phys_addr, res->size);
         |                                                     ^~~~~~~~~
   include/linux/dev_printk.h:154:65: note: expanded from macro 'dev_err'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                                ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ~~~    ^~~~~~~~~~~
   3 warnings generated.


vim +1013 drivers/pci/endpoint/functions/pci-epf-test.c

   972	
   973	static void pci_epf_test_epc_api(struct pci_epf_test *epf_test,
   974					 struct pci_epf_test_reg *reg)
   975	{
   976		struct pci_epc_remote_resource *resources = NULL;
   977		u32 status = le32_to_cpu(reg->status);
   978		struct pci_epf *epf = epf_test->epf;
   979		struct device *dev = &epf->dev;
   980		struct pci_epc *epc = epf->epc;
   981		int num_resources;
   982		int ret, i;
   983	
   984		num_resources = pci_epc_get_remote_resources(epc, epf->func_no,
   985							     epf->vfunc_no, NULL, 0);
   986		if (num_resources == -EOPNOTSUPP || num_resources == 0)
   987			goto out_success;
   988		if (num_resources < 0)
   989			goto err;
   990	
   991		resources = kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);
   992		if (!resources)
   993			goto err;
   994	
   995		ret = pci_epc_get_remote_resources(epc, epf->func_no, epf->vfunc_no,
   996						   resources, num_resources);
   997		if (ret < 0) {
   998			dev_err(dev, "EPC remote resource query failed: %d\n", ret);
   999			goto err_free;
  1000		}
  1001		if (ret > num_resources) {
  1002			dev_err(dev, "EPC API returned %d resources (max %d)\n",
  1003				ret, num_resources);
  1004			goto err_free;
  1005		}
  1006	
  1007		for (i = 0; i < ret; i++) {
  1008			struct pci_epc_remote_resource *res = &resources[i];
  1009	
  1010			if (!res->phys_addr || !res->size) {
  1011				dev_err(dev,
  1012					"Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
> 1013					i, res->type, &res->phys_addr, res->size);
  1014				goto err_free;
  1015			}
  1016	
  1017			/* Guard against address overflow */
  1018			if (res->phys_addr + res->size < res->phys_addr) {
  1019				dev_err(dev,
  1020					"Remote resource[%d] overflow (phys=%pa size=%llu)\n",
  1021					i, &res->phys_addr, res->size);
  1022				goto err_free;
  1023			}
  1024	
  1025			switch (res->type) {
  1026			case PCI_EPC_RR_DMA_CTRL_MMIO:
  1027				/* Generic checks above are sufficient. */
  1028				break;
  1029			case PCI_EPC_RR_DMA_CHAN_DESC:
  1030				/*
  1031				 * hw_chan_id and ep2rc are informational. No extra validation
  1032				 * beyond the generic checks above is needed.
  1033				 */
  1034				break;
  1035			default:
  1036				dev_err(dev, "Unknown remote resource type %d\n", res->type);
  1037				goto err_free;
  1038			}
  1039		}
  1040	
  1041	out_success:
  1042		kfree(resources);
  1043		status |= STATUS_EPC_API_SUCCESS;
  1044		reg->status = cpu_to_le32(status);
  1045		return;
  1046	
  1047	err_free:
  1048		kfree(resources);
  1049	err:
  1050		status |= STATUS_EPC_API_FAIL;
  1051		reg->status = cpu_to_le32(status);
  1052	}
  1053	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
Posted by kernel test robot 4 days, 21 hours ago
Hi Koichiro,

kernel test robot noticed the following build warnings:

[auto build test WARNING on pci/next]
[also build test WARNING on next-20260204]
[cannot apply to vkoul-dmaengine/next pci/for-linus linus/master v6.19-rc8]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Koichiro-Den/dmaengine-Add-hw_id-to-dma_slave_caps/20260204-230604
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next
patch link:    https://lore.kernel.org/r/20260204145440.950609-10-den%40valinux.co.jp
patch subject: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
config: i386-randconfig-003-20260205 (https://download.01.org/0day-ci/archive/20260205/202602050741.nyI2oa7X-lkp@intel.com/config)
compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260205/202602050741.nyI2oa7X-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602050741.nyI2oa7X-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from include/linux/device.h:15,
                    from include/linux/dmaengine.h:8,
                    from drivers/pci/endpoint/functions/pci-epf-test.c:11:
   drivers/pci/endpoint/functions/pci-epf-test.c: In function 'pci_epf_test_epc_api':
>> drivers/pci/endpoint/functions/pci-epf-test.c:1012:33: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 6 has type 'resource_size_t' {aka 'unsigned int'} [-Wformat=]
    1012 |                                 "Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
         |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ^~~
   include/linux/dev_printk.h:154:56: note: in expansion of macro 'dev_fmt'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                        ^~~~~~~
   drivers/pci/endpoint/functions/pci-epf-test.c:1011:25: note: in expansion of macro 'dev_err'
    1011 |                         dev_err(dev,
         |                         ^~~~~~~
   drivers/pci/endpoint/functions/pci-epf-test.c:1012:88: note: format string is defined here
    1012 |                                 "Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
         |                                                                                     ~~~^
         |                                                                                        |
         |                                                                                        long long unsigned int
         |                                                                                     %u
   drivers/pci/endpoint/functions/pci-epf-test.c:1020:33: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 5 has type 'resource_size_t' {aka 'unsigned int'} [-Wformat=]
    1020 |                                 "Remote resource[%d] overflow (phys=%pa size=%llu)\n",
         |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ^~~
   include/linux/dev_printk.h:154:56: note: in expansion of macro 'dev_fmt'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                        ^~~~~~~
   drivers/pci/endpoint/functions/pci-epf-test.c:1019:25: note: in expansion of macro 'dev_err'
    1019 |                         dev_err(dev,
         |                         ^~~~~~~
   drivers/pci/endpoint/functions/pci-epf-test.c:1020:81: note: format string is defined here
    1020 |                                 "Remote resource[%d] overflow (phys=%pa size=%llu)\n",
         |                                                                              ~~~^
         |                                                                                 |
         |                                                                                 long long unsigned int
         |                                                                              %u


vim +1012 drivers/pci/endpoint/functions/pci-epf-test.c

   972	
   973	static void pci_epf_test_epc_api(struct pci_epf_test *epf_test,
   974					 struct pci_epf_test_reg *reg)
   975	{
   976		struct pci_epc_remote_resource *resources = NULL;
   977		u32 status = le32_to_cpu(reg->status);
   978		struct pci_epf *epf = epf_test->epf;
   979		struct device *dev = &epf->dev;
   980		struct pci_epc *epc = epf->epc;
   981		int num_resources;
   982		int ret, i;
   983	
   984		num_resources = pci_epc_get_remote_resources(epc, epf->func_no,
   985							     epf->vfunc_no, NULL, 0);
   986		if (num_resources == -EOPNOTSUPP || num_resources == 0)
   987			goto out_success;
   988		if (num_resources < 0)
   989			goto err;
   990	
   991		resources = kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);
   992		if (!resources)
   993			goto err;
   994	
   995		ret = pci_epc_get_remote_resources(epc, epf->func_no, epf->vfunc_no,
   996						   resources, num_resources);
   997		if (ret < 0) {
   998			dev_err(dev, "EPC remote resource query failed: %d\n", ret);
   999			goto err_free;
  1000		}
  1001		if (ret > num_resources) {
  1002			dev_err(dev, "EPC API returned %d resources (max %d)\n",
  1003				ret, num_resources);
  1004			goto err_free;
  1005		}
  1006	
  1007		for (i = 0; i < ret; i++) {
  1008			struct pci_epc_remote_resource *res = &resources[i];
  1009	
  1010			if (!res->phys_addr || !res->size) {
  1011				dev_err(dev,
> 1012					"Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
  1013					i, res->type, &res->phys_addr, res->size);
  1014				goto err_free;
  1015			}
  1016	
  1017			/* Guard against address overflow */
  1018			if (res->phys_addr + res->size < res->phys_addr) {
  1019				dev_err(dev,
  1020					"Remote resource[%d] overflow (phys=%pa size=%llu)\n",
  1021					i, &res->phys_addr, res->size);
  1022				goto err_free;
  1023			}
  1024	
  1025			switch (res->type) {
  1026			case PCI_EPC_RR_DMA_CTRL_MMIO:
  1027				/* Generic checks above are sufficient. */
  1028				break;
  1029			case PCI_EPC_RR_DMA_CHAN_DESC:
  1030				/*
  1031				 * hw_chan_id and ep2rc are informational. No extra validation
  1032				 * beyond the generic checks above is needed.
  1033				 */
  1034				break;
  1035			default:
  1036				dev_err(dev, "Unknown remote resource type %d\n", res->type);
  1037				goto err_free;
  1038			}
  1039		}
  1040	
  1041	out_success:
  1042		kfree(resources);
  1043		status |= STATUS_EPC_API_SUCCESS;
  1044		reg->status = cpu_to_le32(status);
  1045		return;
  1046	
  1047	err_free:
  1048		kfree(resources);
  1049	err:
  1050		status |= STATUS_EPC_API_FAIL;
  1051		reg->status = cpu_to_le32(status);
  1052	}
  1053	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
Posted by Frank Li 5 days, 2 hours ago
On Wed, Feb 04, 2026 at 11:54:37PM +0900, Koichiro Den wrote:
> Add a new pci-epf-test command that exercises the newly added EPC API
> pci_epc_get_remote_resources().
>
> The test is intentionally a smoke test. It verifies that the API either
> returns -EOPNOTSUPP or a well-formed resource list (non-zero phys/size
> and known resource types). The result is reported to the host via a
> status bit and an interrupt, consistent with existing pci-epf-test
> commands.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
>  drivers/pci/endpoint/functions/pci-epf-test.c | 88 +++++++++++++++++++
>  1 file changed, 88 insertions(+)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> index 6952ee418622..6446a0a23865 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> @@ -35,6 +35,7 @@
>  #define COMMAND_DISABLE_DOORBELL	BIT(7)
>  #define COMMAND_BAR_SUBRANGE_SETUP	BIT(8)
>  #define COMMAND_BAR_SUBRANGE_CLEAR	BIT(9)
> +#define COMMAND_EPC_API			BIT(10)
>
>  #define STATUS_READ_SUCCESS		BIT(0)
>  #define STATUS_READ_FAIL		BIT(1)
> @@ -54,6 +55,8 @@
>  #define STATUS_BAR_SUBRANGE_SETUP_FAIL		BIT(15)
>  #define STATUS_BAR_SUBRANGE_CLEAR_SUCCESS	BIT(16)
>  #define STATUS_BAR_SUBRANGE_CLEAR_FAIL		BIT(17)
> +#define STATUS_EPC_API_SUCCESS		BIT(18)
> +#define STATUS_EPC_API_FAIL		BIT(19)
>
>  #define FLAG_USE_DMA			BIT(0)
>
> @@ -967,6 +970,87 @@ static void pci_epf_test_bar_subrange_clear(struct pci_epf_test *epf_test,
>  	reg->status = cpu_to_le32(status);
>  }
>
> +static void pci_epf_test_epc_api(struct pci_epf_test *epf_test,
> +				 struct pci_epf_test_reg *reg)
> +{
> +	struct pci_epc_remote_resource *resources = NULL;
> +	u32 status = le32_to_cpu(reg->status);
> +	struct pci_epf *epf = epf_test->epf;
> +	struct device *dev = &epf->dev;
> +	struct pci_epc *epc = epf->epc;
> +	int num_resources;
> +	int ret, i;
> +
> +	num_resources = pci_epc_get_remote_resources(epc, epf->func_no,
> +						     epf->vfunc_no, NULL, 0);
> +	if (num_resources == -EOPNOTSUPP || num_resources == 0)
> +		goto out_success;
> +	if (num_resources < 0)
> +		goto err;
> +
> +	resources = kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);

use auto cleanup
	struct pci_epc_remote_resource *resources __free(kfree) =
		kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);

> +	if (!resources)
> +		goto err;
> +
> +	ret = pci_epc_get_remote_resources(epc, epf->func_no, epf->vfunc_no,
> +					   resources, num_resources);
> +	if (ret < 0) {
> +		dev_err(dev, "EPC remote resource query failed: %d\n", ret);
> +		goto err_free;
> +	}
> +	if (ret > num_resources) {
> +		dev_err(dev, "EPC API returned %d resources (max %d)\n",
> +			ret, num_resources);
> +		goto err_free;
> +	}
> +
> +	for (i = 0; i < ret; i++) {
> +		struct pci_epc_remote_resource *res = &resources[i];
> +
> +		if (!res->phys_addr || !res->size) {
> +			dev_err(dev,
> +				"Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
> +				i, res->type, &res->phys_addr, res->size);
> +			goto err_free;
> +		}
> +
> +		/* Guard against address overflow */
> +		if (res->phys_addr + res->size < res->phys_addr) {
> +			dev_err(dev,
> +				"Remote resource[%d] overflow (phys=%pa size=%llu)\n",
> +				i, &res->phys_addr, res->size);
> +			goto err_free;
> +		}
> +
> +		switch (res->type) {
> +		case PCI_EPC_RR_DMA_CTRL_MMIO:
> +			/* Generic checks above are sufficient. */
> +			break;
> +		case PCI_EPC_RR_DMA_CHAN_DESC:
> +			/*
> +			 * hw_chan_id and ep2rc are informational. No extra validation
> +			 * beyond the generic checks above is needed.
> +			 */
> +			break;
> +		default:
> +			dev_err(dev, "Unknown remote resource type %d\n", res->type);
> +			goto err_free;

can you call subrange to map to one of bar?

Frank
> +		}
> +	}
> +
> +out_success:
> +	kfree(resources);
> +	status |= STATUS_EPC_API_SUCCESS;
> +	reg->status = cpu_to_le32(status);
> +	return;
> +
> +err_free:
> +	kfree(resources);
> +err:
> +	status |= STATUS_EPC_API_FAIL;
> +	reg->status = cpu_to_le32(status);
> +}
> +
>  static void pci_epf_test_cmd_handler(struct work_struct *work)
>  {
>  	u32 command;
> @@ -1030,6 +1114,10 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
>  		pci_epf_test_bar_subrange_clear(epf_test, reg);
>  		pci_epf_test_raise_irq(epf_test, reg);
>  		break;
> +	case COMMAND_EPC_API:
> +		pci_epf_test_epc_api(epf_test, reg);
> +		pci_epf_test_raise_irq(epf_test, reg);
> +		break;
>  	default:
>  		dev_err(dev, "Invalid command 0x%x\n", command);
>  		break;
> --
> 2.51.0
>
Re: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for EPC remote resource API
Posted by Koichiro Den 4 days, 14 hours ago
On Wed, Feb 04, 2026 at 02:37:08PM -0500, Frank Li wrote:
> On Wed, Feb 04, 2026 at 11:54:37PM +0900, Koichiro Den wrote:
> > Add a new pci-epf-test command that exercises the newly added EPC API
> > pci_epc_get_remote_resources().
> >
> > The test is intentionally a smoke test. It verifies that the API either
> > returns -EOPNOTSUPP or a well-formed resource list (non-zero phys/size
> > and known resource types). The result is reported to the host via a
> > status bit and an interrupt, consistent with existing pci-epf-test
> > commands.
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> >  drivers/pci/endpoint/functions/pci-epf-test.c | 88 +++++++++++++++++++
> >  1 file changed, 88 insertions(+)
> >
> > diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> > index 6952ee418622..6446a0a23865 100644
> > --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> > +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> > @@ -35,6 +35,7 @@
> >  #define COMMAND_DISABLE_DOORBELL	BIT(7)
> >  #define COMMAND_BAR_SUBRANGE_SETUP	BIT(8)
> >  #define COMMAND_BAR_SUBRANGE_CLEAR	BIT(9)
> > +#define COMMAND_EPC_API			BIT(10)
> >
> >  #define STATUS_READ_SUCCESS		BIT(0)
> >  #define STATUS_READ_FAIL		BIT(1)
> > @@ -54,6 +55,8 @@
> >  #define STATUS_BAR_SUBRANGE_SETUP_FAIL		BIT(15)
> >  #define STATUS_BAR_SUBRANGE_CLEAR_SUCCESS	BIT(16)
> >  #define STATUS_BAR_SUBRANGE_CLEAR_FAIL		BIT(17)
> > +#define STATUS_EPC_API_SUCCESS		BIT(18)
> > +#define STATUS_EPC_API_FAIL		BIT(19)
> >
> >  #define FLAG_USE_DMA			BIT(0)
> >
> > @@ -967,6 +970,87 @@ static void pci_epf_test_bar_subrange_clear(struct pci_epf_test *epf_test,
> >  	reg->status = cpu_to_le32(status);
> >  }
> >
> > +static void pci_epf_test_epc_api(struct pci_epf_test *epf_test,
> > +				 struct pci_epf_test_reg *reg)
> > +{
> > +	struct pci_epc_remote_resource *resources = NULL;
> > +	u32 status = le32_to_cpu(reg->status);
> > +	struct pci_epf *epf = epf_test->epf;
> > +	struct device *dev = &epf->dev;
> > +	struct pci_epc *epc = epf->epc;
> > +	int num_resources;
> > +	int ret, i;
> > +
> > +	num_resources = pci_epc_get_remote_resources(epc, epf->func_no,
> > +						     epf->vfunc_no, NULL, 0);
> > +	if (num_resources == -EOPNOTSUPP || num_resources == 0)
> > +		goto out_success;
> > +	if (num_resources < 0)
> > +		goto err;
> > +
> > +	resources = kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);
> 
> use auto cleanup
> 	struct pci_epc_remote_resource *resources __free(kfree) =
> 		kcalloc(num_resources, sizeof(*resources), GFP_KERNEL);

I'll update it, thanks for pointing that out.
> 
> > +	if (!resources)
> > +		goto err;
> > +
> > +	ret = pci_epc_get_remote_resources(epc, epf->func_no, epf->vfunc_no,
> > +					   resources, num_resources);
> > +	if (ret < 0) {
> > +		dev_err(dev, "EPC remote resource query failed: %d\n", ret);
> > +		goto err_free;
> > +	}
> > +	if (ret > num_resources) {
> > +		dev_err(dev, "EPC API returned %d resources (max %d)\n",
> > +			ret, num_resources);
> > +		goto err_free;
> > +	}
> > +
> > +	for (i = 0; i < ret; i++) {
> > +		struct pci_epc_remote_resource *res = &resources[i];
> > +
> > +		if (!res->phys_addr || !res->size) {
> > +			dev_err(dev,
> > +				"Invalid remote resource[%d] (type=%d phys=%pa size=%llu)\n",
> > +				i, res->type, &res->phys_addr, res->size);
> > +			goto err_free;
> > +		}
> > +
> > +		/* Guard against address overflow */
> > +		if (res->phys_addr + res->size < res->phys_addr) {
> > +			dev_err(dev,
> > +				"Remote resource[%d] overflow (phys=%pa size=%llu)\n",
> > +				i, &res->phys_addr, res->size);
> > +			goto err_free;
> > +		}
> > +
> > +		switch (res->type) {
> > +		case PCI_EPC_RR_DMA_CTRL_MMIO:
> > +			/* Generic checks above are sufficient. */
> > +			break;
> > +		case PCI_EPC_RR_DMA_CHAN_DESC:
> > +			/*
> > +			 * hw_chan_id and ep2rc are informational. No extra validation
> > +			 * beyond the generic checks above is needed.
> > +			 */
> > +			break;
> > +		default:
> > +			dev_err(dev, "Unknown remote resource type %d\n", res->type);
> > +			goto err_free;
> 
> can you call subrange to map to one of bar?

Just for the record, BAR_SUBRANGE_TEST has already landed into the tree and
excercises BAR subrange mapping end-to-end.

In my opinion, simply mapping the returned resources into BAR subranges
here would mostly duplicate the existing subrange test unless we also add
host side validation, and some resource types may be MMIO, so I'd prefer to
keep this as a smoke test. If you had a specific failure mode in mind that
is not covered by BAR_SUBRANGE_TEST, please let me know, I can try to add a
targeted check.

Thanks for the review,
Koichiro

> 
> Frank
> > +		}
> > +	}
> > +
> > +out_success:
> > +	kfree(resources);
> > +	status |= STATUS_EPC_API_SUCCESS;
> > +	reg->status = cpu_to_le32(status);
> > +	return;
> > +
> > +err_free:
> > +	kfree(resources);
> > +err:
> > +	status |= STATUS_EPC_API_FAIL;
> > +	reg->status = cpu_to_le32(status);
> > +}
> > +
> >  static void pci_epf_test_cmd_handler(struct work_struct *work)
> >  {
> >  	u32 command;
> > @@ -1030,6 +1114,10 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
> >  		pci_epf_test_bar_subrange_clear(epf_test, reg);
> >  		pci_epf_test_raise_irq(epf_test, reg);
> >  		break;
> > +	case COMMAND_EPC_API:
> > +		pci_epf_test_epc_api(epf_test, reg);
> > +		pci_epf_test_raise_irq(epf_test, reg);
> > +		break;
> >  	default:
> >  		dev_err(dev, "Invalid command 0x%x\n", command);
> >  		break;
> > --
> > 2.51.0
> >