RE: [PATCH v2 07/27] ocxl: Add functions to map/unmap LPC memory
From: Alastair D'Silva <hidden>
Date: 2020-02-19 02:39:15
Also in:
linux-mm, lkml, nvdimm
On Mon, 2020-02-03 at 12:49 +0000, Jonathan Cameron wrote:
On Tue, 3 Dec 2019 14:46:35 +1100 Alastair D'Silva [off-list ref] wrote:quoted
From: Alastair D'Silva <redacted> Add functions to map/unmap LPC memory Signed-off-by: Alastair D'Silva <redacted> --- drivers/misc/ocxl/config.c | 4 +++ drivers/misc/ocxl/core.c | 50 +++++++++++++++++++++++++++++++ drivers/misc/ocxl/ocxl_internal.h | 3 ++ include/misc/ocxl.h | 18 +++++++++++ 4 files changed, 75 insertions(+)diff --git a/drivers/misc/ocxl/config.cb/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(structpci_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); +If we are being fussy, this block has nothing todo with the rest of the patch so we should be seeing it here.
Agreed
quoted
return 0; }diff --git a/drivers/misc/ocxl/core.c b/drivers/misc/ocxl/core.c index 2531c6cf19a0..98611faea219 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_afu_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-quoted
config.special_purpose_mem_size) == 0)+ return 0; + + afu->lpc_base_addr = ocxl_link_lpc_map(afu->fn->link, dev); + if (afu->lpc_base_addr == 0) + return -EINVAL; + + if (afu->config.lpc_mem_size) {I was happy with the explicit check on 0 above, but we should be consistent. Either we make use of 0 == false, or we don't and explicitly check vs 0. Hence if (afu->config.pc_mem_size != 0) { here or if (!(afu->config.pc_mem_size + afu-quoted
config.special_purpose_mem_size))return 0; above.
This feels a bit niggly, but sure, changed to a '> 0' check.
quoted
+ afu->lpc_res.start = afu->lpc_base_addr + afu-quoted
config.lpc_mem_offset;+ afu->lpc_res.end = afu->lpc_res.start + afu-quoted
config.lpc_mem_size - 1;+ } + + if (afu->config.special_purpose_mem_size) { + afu->special_purpose_res.start = afu->lpc_base_addr + + afu-quoted
config.special_purpose_mem_offset;+ afu->special_purpose_res.end = afu-quoted
special_purpose_res.start ++ afu-quoted
config.special_purpose_mem_size - 1;+ } + + return 0; +} +EXPORT_SYMBOL_GPL(ocxl_afu_map_lpc_mem); + +struct resource *ocxl_afu_lpc_mem(struct ocxl_afu *afu) +{ + return &afu->lpc_res; +} +EXPORT_SYMBOL_GPL(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_release(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;@@ -251,6 +300,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);Hmm. This breaks the existing balance between configure_afu and deconfigure_afu. Given comments below on why we don't do map_lpc_mem in the afu bring up (as it's a shared operation) it seems to me that we should be doing this outside of the afu deconfigure. Perhaps ocxl_function_close is appropriate? I don't know this infrastructure well enough to be sure. If it does need to be here, then a comment to give more info on why would be great!
Sure, I've added a comment in unmap_lpc_mem explaining that lpc_release only releases the memory on the link when the last consumer calls release. It's in deconfigure_afu as the LPC memory is registered and reported per-AFU (even though it has to be allocated all at once across the link).
quoted
unmap_mmio_areas(afu); reclaim_afu_pasid(afu); reclaim_afu_actag(afu);diff --git a/drivers/misc/ocxl/ocxl_internal.hb/drivers/misc/ocxl/ocxl_internal.h index 20b417e00949..9f4b47900e62 100644--- a/drivers/misc/ocxl/ocxl_internal.h +++ b/drivers/misc/ocxl/ocxl_internal.h@@ -52,6 +52,9 @@ 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 resource lpc_res; + struct resource special_purpose_res; }; enum ocxl_context_status {diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h index 06dd5839e438..6f7c02f0d5e3 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 mapRun kernel-doc over these files and fix all the errors + warnings.
Ok.
@afu: .. and missing function name etc.quoted
+ */ +extern int ocxl_afu_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 *
-- Alastair D'Silva Open Source Developer Linux Technology Centre, IBM Australia mob: 0423 762 819