From: Alastair D'Silva <alast...@d-silva.org> Add functions to map/unmap LPC memory
Signed-off-by: Alastair D'Silva <alast...@d-silva.org> --- drivers/misc/ocxl/config.c | 4 +++ drivers/misc/ocxl/core.c | 50 +++++++++++++++++++++++++++++++ drivers/misc/ocxl/link.c | 4 +-- drivers/misc/ocxl/ocxl_internal.h | 10 +++++-- include/misc/ocxl.h | 18 +++++++++++ 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c index c8e19bfb5ef9..fb0c3b6f8312 100644 --- a/drivers/misc/ocxl/config.c +++ b/drivers/misc/ocxl/config.c @@ -568,6 +568,10 @@ static int read_afu_lpc_memory_info(struct pci_dev *dev, afu->special_purpose_mem_size = total_mem_size - lpc_mem_size; } + + dev_info(&dev->dev, "Probed LPC memory of %#llx bytes and special purpose memory of %#llx bytes\n", + afu->lpc_mem_size, afu->special_purpose_mem_size); + return 0; } diff --git a/drivers/misc/ocxl/core.c b/drivers/misc/ocxl/core.c index fdfe4e0a34e1..eb24bb9d655f 100644 --- a/drivers/misc/ocxl/core.c +++ b/drivers/misc/ocxl/core.c @@ -210,6 +210,55 @@ static void unmap_mmio_areas(struct ocxl_afu *afu) release_fn_bar(afu->fn, afu->config.global_mmio_bar); } +int ocxl_map_lpc_mem(struct ocxl_afu *afu) +{ + struct pci_dev *dev = to_pci_dev(afu->fn->dev.parent); + + if ((afu->config.lpc_mem_size + afu->config.special_purpose_mem_size) == 0) + return 0; + + afu->lpc_base_addr = ocxl_link_lpc_online(afu->fn->link, dev); + if (afu->lpc_base_addr == 0) + return -EINVAL; + + if (afu->config.lpc_mem_size) { + afu->lpc_res.start = afu->lpc_base_addr + afu->config.lpc_mem_offset; + afu->lpc_res.end = afu->lpc_res.start + afu->config.lpc_mem_size - 1; + } + + if (afu->config.special_purpose_mem_size) { + afu->special_purpose_res.start = afu->lpc_base_addr + + afu->config.special_purpose_mem_offset; + afu->special_purpose_res.end = afu->special_purpose_res.start + + afu->config.special_purpose_mem_size - 1; + } + + return 0; +} +EXPORT_SYMBOL(ocxl_map_lpc_mem); + +struct resource *ocxl_afu_lpc_mem(struct ocxl_afu *afu) +{ + return &afu->lpc_res; +} +EXPORT_SYMBOL(ocxl_afu_lpc_mem); + +static void unmap_lpc_mem(struct ocxl_afu *afu) +{ + struct pci_dev *dev = to_pci_dev(afu->fn->dev.parent); + + if (afu->lpc_res.start || afu->special_purpose_res.start) { + void *link = afu->fn->link; + + ocxl_link_lpc_offline(link, dev); + + afu->lpc_res.start = 0; + afu->lpc_res.end = 0; + afu->special_purpose_res.start = 0; + afu->special_purpose_res.end = 0; + } +} + static int configure_afu(struct ocxl_afu *afu, u8 afu_idx, struct pci_dev *dev) { int rc; @@ -250,6 +299,7 @@ static int configure_afu(struct ocxl_afu *afu, u8 afu_idx, struct pci_dev *dev) static void deconfigure_afu(struct ocxl_afu *afu) { + unmap_lpc_mem(afu); unmap_mmio_areas(afu); reclaim_afu_pasid(afu); reclaim_afu_actag(afu); diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c index 2874811a4398..9e303a5f4d85 100644 --- a/drivers/misc/ocxl/link.c +++ b/drivers/misc/ocxl/link.c @@ -738,7 +738,7 @@ int ocxl_link_add_lpc_mem(void *link_handle, u64 size) } EXPORT_SYMBOL_GPL(ocxl_link_add_lpc_mem); -u64 ocxl_link_lpc_map(void *link_handle, struct pci_dev *pdev) +u64 ocxl_link_lpc_online(void *link_handle, struct pci_dev *pdev) { struct ocxl_link *link = (struct ocxl_link *) link_handle; @@ -759,7 +759,7 @@ u64 ocxl_link_lpc_map(void *link_handle, struct pci_dev *pdev) return link->lpc_mem; } -void ocxl_link_lpc_release(void *link_handle, struct pci_dev *pdev) +void ocxl_link_lpc_offline(void *link_handle, struct pci_dev *pdev) { struct ocxl_link *link = (struct ocxl_link *) link_handle; diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h index db2647a90fc8..5656a4aab5b7 100644 --- a/drivers/misc/ocxl/ocxl_internal.h +++ b/drivers/misc/ocxl/ocxl_internal.h @@ -52,6 +52,12 @@ struct ocxl_afu { void __iomem *global_mmio_ptr; u64 pp_mmio_start; void *private; + u64 lpc_base_addr; /* Covers both LPC & special purpose memory */ + struct bin_attribute attr_global_mmio; + struct bin_attribute attr_lpc_mem; + struct resource lpc_res; + struct bin_attribute attr_special_purpose_mem; + struct resource special_purpose_res; }; enum ocxl_context_status { @@ -170,7 +176,7 @@ extern u64 ocxl_link_get_lpc_mem_sz(void *link_handle); * @link_handle: The OpenCAPI link handle * @pdev: A device that is on the link */ -u64 ocxl_link_lpc_map(void *link_handle, struct pci_dev *pdev); +u64 ocxl_link_lpc_online(void *link_handle, struct pci_dev *pdev); /** * Release the LPC memory device for an OpenCAPI device @@ -181,6 +187,6 @@ u64 ocxl_link_lpc_map(void *link_handle, struct pci_dev *pdev); * @link_handle: The OpenCAPI link handle * @pdev: A device that is on the link */ -void ocxl_link_lpc_release(void *link_handle, struct pci_dev *pdev); +void ocxl_link_lpc_offline(void *link_handle, struct pci_dev *pdev); #endif /* _OCXL_INTERNAL_H_ */ diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h index 06dd5839e438..a1897737908d 100644 --- a/include/misc/ocxl.h +++ b/include/misc/ocxl.h @@ -212,6 +212,24 @@ int ocxl_irq_set_handler(struct ocxl_context *ctx, int irq_id, // AFU Metadata +/** + * Map the LPC system & special purpose memory for an AFU + * + * Do not call this during device discovery, as there may me multiple + * devices on a link, and the memory is mapped for the whole link, not + * just one device. It should only be called after all devices have + * registered their memory on the link. + * + * afu: The AFU that has the LPC memory to map + */ +extern int ocxl_map_lpc_mem(struct ocxl_afu *afu); + +/** + * Get the physical address range of LPC memory for an AFU + * afu: The AFU associated with the LPC memory + */ +extern struct resource *ocxl_afu_lpc_mem(struct ocxl_afu *afu); + /** * Get a pointer to the config for an AFU * -- 2.21.0