diff options
author | Andrew Donnellan <ajd@linux.ibm.com> | 2020-01-28 18:19:56 +1100 |
---|---|---|
committer | Oliver O'Halloran <oohall@gmail.com> | 2020-01-29 13:51:35 +1100 |
commit | bc72973d1321546a43f03367b5e73d8ff83a83bd (patch) | |
tree | 3d30b8625c137e24acd7146c4aa1d6e9ee1c8352 /hw/npu2-opencapi.c | |
parent | 8b9be4913366b02dbdb43bb8ddc7028a6e9129af (diff) | |
download | skiboot-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.c | 49 |
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); |