aboutsummaryrefslogtreecommitdiff
path: root/hw/pau.c
diff options
context:
space:
mode:
authorChristophe Lombard <clombard@linux.vnet.ibm.com>2021-10-14 17:57:04 +0200
committerVasant Hegde <hegdevasant@linux.vnet.ibm.com>2021-10-19 12:26:02 +0530
commit4c1add1fb20fe07b827227ca34f63f176774d51c (patch)
tree6f191cb95c848d7bbf2268231cc62f7d8719f0d0 /hw/pau.c
parent2d89dd334756d19a9ffc3e4c784406177f46c053 (diff)
downloadskiboot-4c1add1fb20fe07b827227ca34f63f176774d51c.zip
skiboot-4c1add1fb20fe07b827227ca34f63f176774d51c.tar.gz
skiboot-4c1add1fb20fe07b827227ca34f63f176774d51c.tar.bz2
pau: Add support for OpenCAPI Persistent Memory devices.
Lowest Point of Coherency (LPC) memory allows the host to access memory on an OpenCAPI device. When the P10 chip accesses memory addresses on the AFU, the Real Address on the PowerBus must hit a BAR in the PAU such as GPU-Memory BAR. The BAR defines the range of Real Addresses that represent AFU memory. The two existing OPAL calls, OPAL_NPU_MEM_ALLOC and OPAL_NPU_MEM_RELEASE are used to manage the AFU momory. Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Diffstat (limited to 'hw/pau.c')
-rw-r--r--hw/pau.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/hw/pau.c b/hw/pau.c
index 9f6a709..a34d6da 100644
--- a/hw/pau.c
+++ b/hw/pau.c
@@ -442,6 +442,99 @@ int64_t pau_opencapi_tl_set(struct phb *phb, uint32_t __unused bdfn,
return OPAL_SUCCESS;
}
+static int64_t pau_opencapi_afu_memory_bars(struct pau_dev *dev,
+ uint64_t size,
+ uint64_t *bar)
+{
+ struct pau *pau = dev->pau;
+ uint64_t addr, psize;
+ uint64_t reg, val;
+
+ PAUDEVDBG(dev, "Setup AFU Memory BARs\n");
+
+ if (dev->memory_bar.enable) {
+ PAUDEVERR(dev, "AFU memory allocation failed - BAR already in use\n");
+ return OPAL_RESOURCE;
+ }
+
+ phys_map_get(pau->chip_id, OCAPI_MEM,
+ dev->index,
+ &addr, &psize);
+
+ if (size > psize) {
+ PAUDEVERR(dev, "Invalid AFU memory BAR allocation size "
+ "requested: 0x%llx bytes (limit 0x%llx)\n",
+ size, psize);
+ return OPAL_PARAMETER;
+ }
+
+ if (size < (1 << 30))
+ size = 1 << 30;
+
+ dev->memory_bar.enable = true;
+ dev->memory_bar.addr = addr;
+ dev->memory_bar.size = size;
+
+ reg = PAU_GPU_MEM_BAR(dev->index);
+ val = PAU_GPU_MEM_BAR_ENABLE |
+ PAU_GPU_MEM_BAR_POISON;
+ val = SETFIELD(PAU_GPU_MEM_BAR_ADDR, val, addr >> 30);
+ if (!is_pow2(size))
+ size = 1ull << (ilog2(size) + 1);
+
+ size = (size >> 30) - 1;
+ val = SETFIELD(PAU_GPU_MEM_BAR_SIZE, val, size);
+ pau_write(pau, reg, val);
+
+ reg = PAU_CTL_MISC_GPU_MEM_BAR(dev->index);
+ pau_write(pau, reg, val);
+
+ reg = PAU_XSL_GPU_MEM_BAR(dev->index);
+ pau_write(pau, reg, val);
+
+ *bar = addr;
+ return OPAL_SUCCESS;
+}
+
+int64_t pau_opencapi_mem_alloc(struct phb *phb, uint32_t __unused bdfn,
+ uint64_t size, uint64_t *bar)
+{
+ struct pau_dev *dev = pau_phb_to_opencapi_dev(phb);
+ int64_t rc;
+
+ if (!dev)
+ return OPAL_PARAMETER;
+
+ if (!opal_addr_valid(bar))
+ return OPAL_PARAMETER;
+
+ lock(&dev->pau->lock);
+ rc = pau_opencapi_afu_memory_bars(dev, size, bar);
+
+ unlock(&dev->pau->lock);
+ return rc;
+}
+
+int64_t pau_opencapi_mem_release(struct phb *phb, uint32_t __unused bdfn)
+{
+ struct pau_dev *dev = pau_phb_to_opencapi_dev(phb);
+
+ if (!dev)
+ return OPAL_PARAMETER;
+
+ lock(&dev->pau->lock);
+ pau_write(dev->pau, PAU_GPU_MEM_BAR(dev->index), 0ull);
+ pau_write(dev->pau, PAU_CTL_MISC_GPU_MEM_BAR(dev->index), 0ull);
+ pau_write(dev->pau, PAU_XSL_GPU_MEM_BAR(dev->index), 0ull);
+
+ dev->memory_bar.enable = false;
+ dev->memory_bar.addr = 0ull;
+ dev->memory_bar.size = 0ull;
+ unlock(&dev->pau->lock);
+
+ return OPAL_SUCCESS;
+}
+
#define CQ_CTL_STATUS_TIMEOUT 10 /* milliseconds */
static int pau_opencapi_set_fence_control(struct pau_dev *dev,