From: Aksh Garg <a-garg7@ti.com>
To: <linux-pci@vger.kernel.org>, <linux-doc@vger.kernel.org>,
<mani@kernel.org>, <kwilczynski@kernel.org>,
<bhelgaas@google.com>, <corbet@lwn.net>, <kishon@kernel.org>,
<skhan@linuxfoundation.org>, <lukas@wunner.de>,
<cassel@kernel.org>, <alistair@alistair23.me>
Cc: <linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>, <s-vadapalli@ti.com>,
<danishanwar@ti.com>, <srk@ti.com>, <a-garg7@ti.com>
Subject: [PATCH v4 0/4] PCI: Add DOE support for endpoint
Date: Fri, 22 May 2026 10:54:30 +0530 [thread overview]
Message-ID: <20260522052434.802034-1-a-garg7@ti.com> (raw)
This patch series introduces the framework for supporting the Data
Object Exchange (DOE) feature for PCIe endpoint devices. Please refer
to the documentation added in patch 4 for details on the feature and
implementation architecture.
The implementation provides a common framework for all PCIe endpoint
controllers, not specific to any particular SoC vendor.
The changes since v1 are documented in the respective patch descriptions.
v3: https://lore.kernel.org/all/20260427051725.223704-1-a-garg7@ti.com/
v2: https://lore.kernel.org/all/20260401073022.215805-1-a-garg7@ti.com/
v1 (RFC): https://lore.kernel.org/all/20260213123603.420941-1-a-garg7@ti.com/
Below is a code demonstration showing the integration of DOE-EP APIs with
EPC drivers.
Note: The provided code is just to show how an EPC driver is expected to
utilize the pci_ep_doe_process_request() and pci_ep_doe_abort() APIs,
and might not cover all the corner cases. The below implementation
also expects the EPC hardware to have some memory buffer to store the
data from(for) write_mailbox(read_mailbox) DOE capability registers.
============================================================================
/* ========== DOE Completion Callback (invoked by DOE-EP core) ========== */
static void doe_completion_cb(struct pci_epc *epc, u8 func_no, u16 cap_offset,
int status, u16 vendor, u8 type,
void *response_pl, size_t response_pl_sz)
{
struct epc_driver *drv = epc_get_drvdata(epc);
u32 *response = (u32 *)response_pl;
u32 header1, header2;
int payload_dw, i;
if (status < 0) {
/* Error: set ERROR bit in DOE Status register */
writel(1 << DOE_STATUS_ERROR,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
goto free;
}
if (readl(drv->base + PF_DOE_CTRL_REG(func_no, cap_offset)) & DOE_CTRL_ABORT) {
/* Aborted: do not send response */
goto free;
}
/* Success: write DOE headers first, then response to the read memory */
/* Header 1: Vendor ID (bits 15:0) | Type (bits 23:16) */
header1 = (type << 16) | vendor;
writel(header1, drv->base + PF_DOE_RD_MEMORY_WR_REG(func_no, cap_offset));
/* Header 2: Length in DW (including 2 DW of headers + payload) */
payload_dw = DIV_ROUND_UP(response_pl_sz, sizeof(u32));
header2 = 2 + payload_dw; /* 2 header DWs + payload */
writel(header2, drv->base + PF_DOE_RD_MEMORY_WR_REG(func_no, cap_offset));
/* Set READY bit to signal response ready */
writel(1 << DOE_STATUS_READY,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
/* Write response payload DWORDs to Read memory */
for (i = 0; i < payload_dw; i++)
writel(response[i],
drv->base + PF_DOE_RD_MEMORY_WR_REG(func_no, cap_offset));
/* Wait for the memory to empty before clearing the READY bit */
while (!RD_MEMORY_EMPTY()) {/* wait */}
writel(0 << DOE_STATUS_READY,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
/* unset BUSY bit */
writel(0 << DOE_STATUS_BUSY,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
free:
kfree(response_pl);
}
/* ========== DOE Interrupt Handler (triggered on GO bit from root complex) ========== */
static irqreturn_t doe_interrupt_handler(int irq, void *priv)
{
struct epc_driver *drv = priv;
u16 cap_offset = extract_cap_offset_from_irq(irq);
u8 func_no = extract_func_from_irq(irq);
u32 header1, header2, length_dw, *request;
u16 vendor;
u8 type;
int i, ret;
/* Read first header DWORD: Vendor ID (bits 15:0) | Type (bits 23:16) */
header1 = readl(drv->base + PF_DOE_WR_MEMORY_RD_REG(func_no, cap_offset));
vendor = header1 & 0xFFFF;
type = (header1 >> 16) & 0xFF;
/* Read second header DWORD: Length in DW (includes 2 DW of headers) */
header2 = readl(drv->base + PF_DOE_WR_MEMORY_RD_REG(func_no, cap_offset));
length_dw = header2 & 0x3FFFF; /* Bits 17:0 */
if (!length_dw)
length_dw = PCI_DOE_MAX_LENGTH;
length_dw -= 2; /* Subtract 2 DW of headers to get payload length */
/* Allocate buffer for complete request (headers + payload) */
request = kzalloc(length_dw * sizeof(u32), GFP_ATOMIC);
if (!request) {
writel(1 << DOE_STATUS_ERROR,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
return IRQ_HANDLED;
}
/* Read remaining payload DWORDs from Write memory */
for (i = 0; i < length_dw; i++) {
while (WR_MEMORY_EMPTY()) { /* wait */ }
request[i] = readl(drv->base + PF_DOE_WR_MEMORY_RD_REG(func_no, cap_offset));
}
/* Set BUSY bit */
writel(1 << DOE_STATUS_BUSY,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
/* Hand off to DOE-EP core for asynchronous processing */
ret = pci_ep_doe_process_request(drv->epc, func_no, cap_offset,
vendor, type, (void *)request,
length_dw * sizeof(u32),
doe_completion_cb);
if (ret) {
writel(1 << DOE_STATUS_ERROR,
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
kfree(request);
}
return IRQ_HANDLED;
}
/* ========== Abort Handler (triggered on ABORT bit from root complex) ========== */
static irqreturn_t doe_abort_handler(int irq, void *priv)
{
struct epc_driver *drv = priv;
u16 cap_offset = extract_cap_offset_from_irq(irq);
u8 func_no = extract_func_from_irq(irq);
/* Abort pending/in-flight operations in DOE-EP core */
pci_ep_doe_abort(drv->epc, func_no, cap_offset);
/* Discard Write memory contents */
writel(DOE_WR_MEMORY_CTRL_DISCARD,
drv->base + PF_DOE_WR_MEMORY_CTRL_REG(func_no, cap_offset));
/* Clear status bits */
writel((0 << DOE_STATUS_ERROR) | (0 << DOE_STATUS_BUSY) |
(0 << DOE_STATUS_READY),
drv->base + PF_DOE_STATUS_REG(func_no, cap_offset));
return IRQ_HANDLED;
}
====================================================================================
Aksh Garg (4):
PCI/DOE: Move common definitions to the header file
PCI: endpoint: Add DOE mailbox support for endpoint functions
PCI: endpoint: Add support for DOE initialization and setup in EPC
core
Documentation: PCI: Add documentation for DOE endpoint support
Documentation/PCI/endpoint/index.rst | 1 +
.../PCI/endpoint/pci-endpoint-doe.rst | 329 +++++++++++
drivers/pci/doe.c | 11 -
drivers/pci/endpoint/Kconfig | 14 +
drivers/pci/endpoint/Makefile | 1 +
drivers/pci/endpoint/pci-ep-doe.c | 553 ++++++++++++++++++
drivers/pci/endpoint/pci-epc-core.c | 92 +++
drivers/pci/pci.h | 48 ++
include/linux/pci-doe.h | 8 +
include/linux/pci-epc.h | 9 +
10 files changed, 1055 insertions(+), 11 deletions(-)
create mode 100644 Documentation/PCI/endpoint/pci-endpoint-doe.rst
create mode 100644 drivers/pci/endpoint/pci-ep-doe.c
--
2.34.1
next reply other threads:[~2026-05-22 5:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-22 5:24 Aksh Garg [this message]
2026-05-22 5:24 ` [PATCH v4 1/4] PCI/DOE: Move common definitions to the header file Aksh Garg
2026-05-22 5:24 ` [PATCH v4 2/4] PCI: endpoint: Add DOE mailbox support for endpoint functions Aksh Garg
2026-05-22 5:24 ` [PATCH v4 3/4] PCI: endpoint: Add support for DOE initialization and setup in EPC core Aksh Garg
2026-05-22 5:24 ` [PATCH v4 4/4] Documentation: PCI: Add documentation for DOE endpoint support Aksh Garg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260522052434.802034-1-a-garg7@ti.com \
--to=a-garg7@ti.com \
--cc=alistair@alistair23.me \
--cc=bhelgaas@google.com \
--cc=cassel@kernel.org \
--cc=corbet@lwn.net \
--cc=danishanwar@ti.com \
--cc=kishon@kernel.org \
--cc=kwilczynski@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=mani@kernel.org \
--cc=s-vadapalli@ti.com \
--cc=skhan@linuxfoundation.org \
--cc=srk@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox