From: Koichiro Den Date: Tue, 14 Apr 2026 14:15:08 +0000 (+0900) Subject: PCI: endpoint: Add auxiliary resource query API X-Git-Tag: v7.2-rc1~40^2~21^2~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc07b903a646bf6592182b27c63457d92f128125;p=thirdparty%2Flinux.git PCI: endpoint: Add auxiliary resource query API Endpoint controller drivers may integrate auxiliary blocks (e.g. DMA engines) whose register windows and descriptor memories metadata need to be exposed to a remote peer. Endpoint function drivers need a generic way to discover such resources without hard-coding controller-specific helpers. Add pci_epc_get_aux_resources_count() / pci_epc_get_aux_resources() and the corresponding pci_epc_ops callbacks. The count helper returns the number of available resources, while the get helper fills a caller-provided array of resources described by type, physical address and size, plus type-specific metadata. Suggested-by: Manivannan Sadhasivam Suggested-by: Frank Li Signed-off-by: Koichiro Den Signed-off-by: Manivannan Sadhasivam Link: https://patch.msgid.link/20260414141514.1341429-2-den@valinux.co.jp --- diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 6c3c58185fc5d..831b40458dcd8 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -156,6 +156,86 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc, } EXPORT_SYMBOL_GPL(pci_epc_get_features); +/** + * pci_epc_get_aux_resources_count() - get the number of EPC-provided auxiliary resources + * @epc: EPC device + * @func_no: function number + * @vfunc_no: virtual function number + * + * Some EPC backends integrate auxiliary blocks (e.g. DMA engines) whose control + * registers and/or descriptor memories can be exposed to the host by mapping + * them into BAR space. This helper queries how many such resources the backend + * provides. + * + * Return: the number of available resources on success, -EOPNOTSUPP if the + * backend does not support auxiliary resource queries, or another -errno on + * failure. + */ +int pci_epc_get_aux_resources_count(struct pci_epc *epc, u8 func_no, + u8 vfunc_no) +{ + int count; + + if (!epc || !epc->ops) + return -EINVAL; + + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) + return -EINVAL; + + if (!epc->ops->get_aux_resources_count) + return -EOPNOTSUPP; + + mutex_lock(&epc->lock); + count = epc->ops->get_aux_resources_count(epc, func_no, + vfunc_no); + mutex_unlock(&epc->lock); + + return count; +} +EXPORT_SYMBOL_GPL(pci_epc_get_aux_resources_count); + +/** + * pci_epc_get_aux_resources() - query EPC-provided auxiliary resources + * @epc: EPC device + * @func_no: function number + * @vfunc_no: virtual function number + * @resources: output array + * @num_resources: size of @resources array in entries + * + * Some EPC backends integrate auxiliary blocks (e.g. DMA engines) whose control + * registers and/or descriptor memories can be exposed to the host by mapping + * them into BAR space. This helper queries the backend for such resources. + * + * Return: 0 on success, -EOPNOTSUPP if the backend does not support auxiliary + * resource queries, or another -errno on failure. + */ +int pci_epc_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_aux_resource *resources, + int num_resources) +{ + int ret; + + if (!resources || num_resources <= 0) + return -EINVAL; + + if (!epc || !epc->ops) + return -EINVAL; + + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) + return -EINVAL; + + if (!epc->ops->get_aux_resources) + return -EOPNOTSUPP; + + mutex_lock(&epc->lock); + ret = epc->ops->get_aux_resources(epc, func_no, vfunc_no, resources, + num_resources); + mutex_unlock(&epc->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(pci_epc_get_aux_resources); + /** * pci_epc_stop() - stop the PCI link * @epc: the link of the EPC device that has to be stopped diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 1eca1264815b2..f247cf9bcf1ac 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -61,6 +61,47 @@ struct pci_epc_map { void __iomem *virt_addr; }; +/** + * enum pci_epc_aux_resource_type - auxiliary resource type identifiers + * @PCI_EPC_AUX_DOORBELL_MMIO: Doorbell MMIO, that might be outside the DMA + * controller register window + * + * EPC backends may expose auxiliary blocks (e.g. DMA engines) by mapping their + * register windows and descriptor memories into BAR space. This enum + * identifies the type of each exposable resource. + */ +enum pci_epc_aux_resource_type { + PCI_EPC_AUX_DOORBELL_MMIO, +}; + +/** + * struct pci_epc_aux_resource - a physical auxiliary resource that may be + * exposed for peer use + * @type: resource type, see enum pci_epc_aux_resource_type + * @phys_addr: physical base address of the resource + * @size: size of the resource in bytes + * @bar: BAR number where this resource is already exposed to the RC + * (NO_BAR if not) + * @bar_offset: offset within @bar where the resource starts (valid iff + * @bar != NO_BAR) + * @u: type-specific metadata + */ +struct pci_epc_aux_resource { + enum pci_epc_aux_resource_type type; + phys_addr_t phys_addr; + resource_size_t size; + enum pci_barno bar; + resource_size_t bar_offset; + + union { + /* PCI_EPC_AUX_DOORBELL_MMIO */ + struct { + int irq; /* IRQ number for the doorbell handler */ + u32 data; /* write value to ring the doorbell */ + } db_mmio; + } u; +}; + /** * struct pci_epc_ops - set of function pointers for performing EPC operations * @write_header: ops to populate configuration space header @@ -84,6 +125,9 @@ struct pci_epc_map { * @start: ops to start the PCI link * @stop: ops to stop the PCI link * @get_features: ops to get the features supported by the EPC + * @get_aux_resources_count: ops to get the number of controller-owned + * auxiliary resources + * @get_aux_resources: ops to retrieve controller-owned auxiliary resources * @owner: the module owner containing the ops */ struct pci_epc_ops { @@ -115,6 +159,11 @@ struct pci_epc_ops { void (*stop)(struct pci_epc *epc); const struct pci_epc_features* (*get_features)(struct pci_epc *epc, u8 func_no, u8 vfunc_no); + int (*get_aux_resources_count)(struct pci_epc *epc, u8 func_no, + u8 vfunc_no); + int (*get_aux_resources)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_aux_resource *resources, + int num_resources); struct module *owner; }; @@ -343,6 +392,11 @@ int pci_epc_start(struct pci_epc *epc); void pci_epc_stop(struct pci_epc *epc); const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc, u8 func_no, u8 vfunc_no); +int pci_epc_get_aux_resources_count(struct pci_epc *epc, u8 func_no, + u8 vfunc_no); +int pci_epc_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_aux_resource *resources, + int num_resources); enum pci_barno pci_epc_get_first_free_bar(const struct pci_epc_features *epc_features); enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features