[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <27zubyj3yzf2mazuq3ub3xmysizbmlpbrnozi32ha2x2cijzhl@exh23bitrsio>
Date: Thu, 5 Feb 2026 16:01:46 +0900
From: Koichiro Den <den@...inux.co.jp>
To: Frank Li <Frank.li@....com>
Cc: vkoul@...nel.org, mani@...nel.org, jingoohan1@...il.com,
lpieralisi@...nel.org, kwilczynski@...nel.org, robh@...nel.org, bhelgaas@...gle.com,
dmaengine@...r.kernel.org, linux-pci@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v3 09/11] PCI: endpoint: pci-epf-test: Add smoke test for
EPC remote resource API
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@...inux.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
> >
Powered by blists - more mailing lists