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_remote_resources() and the corresponding pci_epc_ops get_remote_resources() callback. The API returns a list of resources described by type, physical address and size, plus type-specific metadata. Passing resources == NULL (or num_resources == 0) returns the required number of entries. Signed-off-by: Koichiro Den <[email protected]> --- drivers/pci/endpoint/pci-epc-core.c | 41 +++++++++++++++++++++++++ include/linux/pci-epc.h | 46 +++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 068155819c57..fa161113e24c 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -155,6 +155,47 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc, } EXPORT_SYMBOL_GPL(pci_epc_get_features); +/** + * pci_epc_get_remote_resources() - query EPC-provided remote resources + * @epc: EPC device + * @func_no: function number + * @vfunc_no: virtual function number + * @resources: output array (may be NULL to query required count) + * @num_resources: size of @resources array in entries (0 when querying count) + * + * 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: number of resources returned (or required, if @resources is NULL) + * * -EOPNOTSUPP: backend does not support remote resource queries + * * other -errno on failure + */ +int pci_epc_get_remote_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_remote_resource *resources, + int num_resources) +{ + int ret; + + if (!epc || !epc->ops) + return -EINVAL; + + if (func_no >= epc->max_functions) + return -EINVAL; + + if (!epc->ops->get_remote_resources) + return -EOPNOTSUPP; + + mutex_lock(&epc->lock); + ret = epc->ops->get_remote_resources(epc, func_no, vfunc_no, + resources, num_resources); + mutex_unlock(&epc->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(pci_epc_get_remote_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 c021c7af175f..7d2fce9f3a63 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -61,6 +61,44 @@ struct pci_epc_map { void __iomem *virt_addr; }; +/** + * enum pci_epc_remote_resource_type - remote resource type identifiers + * @PCI_EPC_RR_DMA_CTRL_MMIO: Integrated DMA controller register window (MMIO) + * @PCI_EPC_RR_DMA_CHAN_DESC: Per-channel DMA descriptor + * + * 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_remote_resource_type { + PCI_EPC_RR_DMA_CTRL_MMIO, + PCI_EPC_RR_DMA_CHAN_DESC, +}; + +/** + * struct pci_epc_remote_resource - a physical resource that can be exposed + * @type: resource type, see enum pci_epc_remote_resource_type + * @phys_addr: physical base address of the resource + * @size: size of the resource in bytes + * @u: type-specific metadata + * + * For @PCI_EPC_RR_DMA_CHAN_DESC, @u.dma_chan_desc provides per-channel + * information. + */ +struct pci_epc_remote_resource { + enum pci_epc_remote_resource_type type; + phys_addr_t phys_addr; + resource_size_t size; + + union { + /* PCI_EPC_RR_DMA_CHAN_DESC */ + struct { + int irq; + resource_size_t db_offset; + } dma_chan_desc; + } u; +}; + /** * struct pci_epc_ops - set of function pointers for performing EPC operations * @write_header: ops to populate configuration space header @@ -84,6 +122,8 @@ 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_remote_resources: ops to retrieve controller-owned resources that can be + * exposed to the remote host (optional) * @owner: the module owner containing the ops */ struct pci_epc_ops { @@ -115,6 +155,9 @@ 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_remote_resources)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_remote_resource *resources, + int num_resources); struct module *owner; }; @@ -309,6 +352,9 @@ 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_remote_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_remote_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 -- 2.51.0

