aboutsummaryrefslogtreecommitdiff
path: root/hw/npu2-opencapi.c
diff options
context:
space:
mode:
authorAndrew Donnellan <ajd@linux.ibm.com>2020-01-28 18:19:56 +1100
committerOliver O'Halloran <oohall@gmail.com>2020-01-29 13:51:35 +1100
commitbc72973d1321546a43f03367b5e73d8ff83a83bd (patch)
tree3d30b8625c137e24acd7146c4aa1d6e9ee1c8352 /hw/npu2-opencapi.c
parent8b9be4913366b02dbdb43bb8ddc7028a6e9129af (diff)
downloadskiboot-bc72973d1321546a43f03367b5e73d8ff83a83bd.zip
skiboot-bc72973d1321546a43f03367b5e73d8ff83a83bd.tar.gz
skiboot-bc72973d1321546a43f03367b5e73d8ff83a83bd.tar.bz2
hw/npu2-opencapi: Support multiple LPC devices
Currently, we only have a single range for LPC memory per chip, and we only allow a single device to use that range. With upcoming Hostboot/SBE changes, we'll use the chip address extension mask to give us multiple ranges by using the masked bits of the group ID. Each device can now allocate a whole 4TB non-mirrored region. We still don't do >4TB ranges. If the extension mask is not set correctly, we'll fall back to only permitting one device and printing an error suggesting a firmware upgrade. Signed-off-by: Andrew Donnellan <ajd@linux.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'hw/npu2-opencapi.c')
-rw-r--r--hw/npu2-opencapi.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c
index 133d78b..044993c 100644
--- a/hw/npu2-opencapi.c
+++ b/hw/npu2-opencapi.c
@@ -2181,25 +2181,46 @@ static void set_mem_bar(struct npu2_dev *dev, uint64_t base, uint64_t size)
static int64_t alloc_mem_bar(struct npu2_dev *dev, uint64_t size, uint64_t *bar)
{
- uint64_t phys_map_base, phys_map_size;
+ uint64_t phys_map_base, phys_map_size, val;
int rc = OPAL_SUCCESS;
lock(&dev->npu->lock);
+ if (dev->lpc_mem_base) {
+ OCAPIERR(dev, "LPC allocation failed - BAR already in use\n");
+ rc = OPAL_RESOURCE;
+ goto out;
+ }
+
/*
- * Right now, we support 1 allocation per chip, of up to 4TB.
+ * The supported chip address extension mask is 1100 100 (mask
+ * off 2 bits from group ID and 1 bit from chip ID).
*
- * In future, we will use chip address extension to support
- * >4TB ranges, and we will implement a more sophisticated
- * allocator to allow an allocation for every link on a chip.
+ * Fall back to only permitting a single allocation if we
+ * don't see this mask value.
*/
+ xscom_read(dev->npu->chip_id, PB_CENT_MODE, &val);
+ if (GETFIELD(PB_CFG_CHIP_ADDR_EXTENSION_MASK_CENT, val) == 0b1100100) {
+ phys_map_get(dev->npu->chip_id, OCAPI_MEM,
+ dev->brick_index - 2, &phys_map_base,
+ &phys_map_size);
+ } else {
+ bool in_use = false;
- if (dev->npu->lpc_mem_allocated) {
- rc = OPAL_RESOURCE;
- goto out;
- }
+ for (int i = 0; i < dev->npu->total_devices; i++) {
+ if (dev->npu->devices[i].lpc_mem_base)
+ in_use = true;
+ }
- phys_map_get(dev->npu->chip_id, OCAPI_MEM, 0, &phys_map_base, &phys_map_size);
+ if (in_use) {
+ OCAPIERR(dev, "LPC allocation failed - single device per chip limit, FW upgrade required (pb_cent_mode=0x%016llx)\n", val);
+ rc = OPAL_RESOURCE;
+ goto out;
+ }
+
+ phys_map_get(dev->npu->chip_id, OCAPI_MEM, 0, &phys_map_base,
+ &phys_map_size);
+ }
if (size > phys_map_size) {
/**
@@ -2225,7 +2246,8 @@ static int64_t alloc_mem_bar(struct npu2_dev *dev, uint64_t size, uint64_t *bar)
set_mem_bar(dev, phys_map_base, size);
*bar = phys_map_base;
- dev->npu->lpc_mem_allocated = dev;
+ dev->lpc_mem_base = phys_map_base;
+ dev->lpc_mem_size = size;
out:
unlock(&dev->npu->lock);
@@ -2238,13 +2260,14 @@ static int64_t release_mem_bar(struct npu2_dev *dev)
lock(&dev->npu->lock);
- if (dev->npu->lpc_mem_allocated != dev) {
+ if (!dev->lpc_mem_base) {
rc = OPAL_PARAMETER;
goto out;
}
set_mem_bar(dev, 0, 0);
- dev->npu->lpc_mem_allocated = NULL;
+ dev->lpc_mem_base = 0;
+ dev->lpc_mem_size = 0;
out:
unlock(&dev->npu->lock);