Subject: Re: [PATCH v3 2/4] PCI: endpoint: Add DOE mailbox support for endpoint functions

From: Aksh Garg <[email-masked]>
Date: Tue, 19 May 2026 10:53:40 +0530

On 15/05/26 18:10, Manivannan Sadhasivam wrote:
> On Fri, May 15, 2026 at 11:05:29AM +0530, Aksh Garg wrote:
>>
>>
>> On 14/05/26 13:33, Manivannan Sadhasivam wrote:
>>> On Mon, Apr 27, 2026 at 10:47:23AM +0530, Aksh Garg wrote:
>>>> DOE (Data Object Exchange) is a standard PCIe extended capability
>>>> feature introduced in the Data Object Exchange (DOE) ECN for
>>>> PCIe r5.0. It provides a communication mechanism primarily used for
>>>> implementing PCIe security features such as device authentication, and
>>>> secure link establishment. Think of DOE as a sophisticated mailbox
>>>> system built into PCIe. The root complex can send structured requests
>>>> to the endpoint device through DOE mailboxes, and the endpoint device
>>>> responds with appropriate data.
>>>>
>>>> Add the DOE support for PCIe endpoint devices, enabling endpoint
>>>> functions to process the DOE requests from the host. The implementation
>>>> provides framework APIs for EPC core driver and controller drivers to
>>>> register mailboxes, and request processing with workqueues ensuring
>>>> sequential handling per mailbox, and parallel handling across mailboxes.
>>>> The Discovery protocol is handled internally by the DOE core.
>>>>
>>>> This implementation complements the existing DOE implementation for
>>>> root complex in drivers/pci/doe.c.
>>>>
>>>> Co-developed-by: Siddharth Vadapalli <[email-masked]>
>>>> Signed-off-by: Siddharth Vadapalli <[email-masked]>
>>>> Signed-off-by: Aksh Garg <[email-masked]>
>>>> ---
>>>> +
>>>> +/*
>>>> + * Global registry of protocol handlers.
>>>> + * When a new DOE protocol, library is added, add an entry to this array.
>>>> + */
>>>> +static const struct pci_doe_protocol pci_doe_protocols[] = {
>>>> +	{
>>>> +		.vid = PCI_VENDOR_ID_PCI_SIG,
>>>> +		.type = PCI_DOE_FEATURE_DISCOVERY,
>>>> +		.handler = pci_ep_doe_handle_discovery,
>>>> +	},
>>>> +};
>>>> +
>>>> +/*
>>>> + * Combines function number and capability offset into a unique lookup key
>>>> + * for storing/retrieving DOE mailboxes in an xarray.
>>>> + */
>>>> +#define PCI_DOE_MB_KEY(func, offset) \
>>>> +	(((unsigned long)(func) << 16) | (offset))
>>>> +#define PCI_DOE_PROTOCOL_COUNT        ARRAY_SIZE(pci_doe_protocols)
>>>> +
>>>> +/**
>>>> + * pci_ep_doe_init() - Initialize the DOE framework for a controller in EP mode
>>>> + * @epc: PCI endpoint controller
>>>> + *
>>>> + * Initialize the DOE framework data structures. This only initializes
>>>> + * the xarray that will hold the mailboxes.
>>>> + *
>>>> + * RETURNS: 0 on success, -errno on failure
>>>
>>> kernel-doc format to describe return value is 'Return:' or 'Returns:".
>>
>> Thanks for pointing this out. I will update this.
>>
>>>
>>>> + */
>>>> +int pci_ep_doe_init(struct pci_epc *epc)
>>>> +{
>>>> +	if (!epc)
>>>> +		return -EINVAL;
>>>> +
>>>> +	xa_init(&epc->doe_mbs);
>>>> +	return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(pci_ep_doe_init);
>>>> +
>>
>> [...]
>>
>>>> +
>>>> +/**
>>>> + * pci_ep_doe_process_request() - Process DOE request on endpoint
>>>> + * @epc: PCI endpoint controller
>>>> + * @func_no: Physical function number
>>>> + * @cap_offset: DOE capability offset
>>>> + * @vendor: Vendor ID from request header
>>>> + * @type: Protocol type from request header
>>>> + * @request: Request payload in CPU-native format
>>>> + * @request_sz: Size of request payload (bytes)
>>>> + * @complete: Callback to invoke upon completion
>>>> + *
>>>> + * Asynchronously process a DOE request received on the endpoint. The request
>>>> + * payload should not include the DOE header (vendor/type/length). The protocol
>>>> + * handler will allocate the response buffer, which the caller (controller driver)
>>>> + * must free after use.
>>>> + *
>>>> + * This function returns immediately after queuing the request. The completion
>>>> + * callback will be invoked asynchronously from workqueue context once the
>>>> + * request is processed. The callback receives the function number and capability
>>>> + * offset to identify the mailbox, along with a status code (0 on success, -errno
>>>> + * on failure), and other required arguments.
>>>> + *
>>>> + * As per DOE specification, a mailbox processes one request at a time.
>>>> + * Therefore, this function will never be called concurrently for the same
>>>> + * mailbox by different callers.
>>>> + *
>>>> + * The caller is responsible for the conversion of the received DOE request
>>>> + * with le32_to_cpu() before calling this function.
>>>> + * Similarly, it is responsible for converting the response payload with
>>>> + * cpu_to_le32() before sending it back over the DOE mailbox.
>>>> + *
>>>> + * The caller is also responsible for ensuring that the request size
>>>> + * is within the limits defined by PCI_DOE_MAX_LENGTH.
>>>> + *
>>>> + * RETURNS: 0 if the request was successfully queued, -errno on failure
>>>> + */
>>>> +int pci_ep_doe_process_request(struct pci_epc *epc, u8 func_no, u16 cap_offset,
>>>> +			       u16 vendor, u8 type, const void *request, size_t request_sz,
>>>> +			       pci_ep_doe_complete_t complete)
>>>> +{
>>>> +	struct pci_ep_doe_mb *doe_mb;
>>>> +	struct pci_ep_doe_task *task;
>>>> +	int rc;
>>>> +
>>>> +	doe_mb = pci_ep_doe_get_mailbox(epc, func_no, cap_offset);
>>>> +	if (!doe_mb) {
>>>> +		kfree(request);
>>>> +		return -ENODEV;
>>>> +	}
>>>> +
>>>> +	task = kzalloc_obj(*task, GFP_KERNEL);
>>>> +	if (!task) {
>>>> +		kfree(request);
>>>> +		return -ENOMEM;
>>>> +	}
>>>> +
>>>> +	task->feat.vid = vendor;
>>>> +	task->feat.type = type;
>>>> +	task->request_pl = request;
>>>> +	task->request_pl_sz = request_sz;
>>>> +	task->response_pl = NULL;
>>>> +	task->response_pl_sz = 0;
>>>> +	task->complete = complete;
>>>> +
>>>> +	rc = pci_ep_doe_submit_task(doe_mb, task);
>>>> +	if (rc) {
>>>> +		kfree(request);
>>>> +		kfree(task);
>>>> +		return rc;
>>>> +	}
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(pci_ep_doe_process_request);
>>>
>>> So who is supposed to call this API? EPC driver that receives the DOE interrupt?
>>
>> Yes, the EPC drivers that receive the DOE interrupts are expected to
>> call this API.
>>
>>> But I don't see the any callers of this and below exported APIs in this series.
>>> Either you should add the callers or limit this series just to adding the DOE
>>> skeleton implementation with a clear follow-up.
>>
>> I currently am working on the EPC driver implementation for a platform
>> which has not been up-streamed yet. I plan to use these APIs to support
>> the DOE feature for that driver. Currently, I am not aware of any
>> platform whose EPC driver supports DOE feature and its interrupts, hence
>> I see no real callers of these APIs to include in this patch series.
>>
>> Would it be appropriate to add a dummy [NOT-FOR-MERGING] demonstration
>> patch over an existing EPC driver, showing how these DOE APIs would be
>> integrated into an EPC driver?
>>
> 
> Usually we don't add APIs without any callers. But if you have a realistic time
> frame and guarantee that you are going to add EPC driver support soon, then we
> can have these APIs merged first.
> 

Hi Mani,

The expected timeline for adding the upstream support for the platform
is by the end of Q3. Once it gets merged, we would post the patches to
add its EPC as well as downstream driver support on top of it.

> For demonstration purpose, you can just show the EPC integration as a snippet in
> cover letter or point to the downstream driver for reference (if it is not a
> secret sauce).

Sure, I will add a dummy EPC integration code in the cover letter to 
demonstrate the usage of those APIs.

Thanks.

> - Mani