[Skiboot] [PATCH 03/13] hw/npu2: Move PHY/NTL/GENID BAR assignment to common code

Frederic Barrat fbarrat at linux.ibm.com
Fri Dec 14 02:18:29 AEDT 2018



Le 12/12/2018 à 07:58, Andrew Donnellan a écrit :
> Assignment of PHY/NTL/GENID BARs is currently duplicated between NVLink
> and OpenCAPI. This is going to cause us particular issues later on when we
> implement support for mixed-mode setups with NVLink and OpenCAPI on the
> same NPU.
> 
> Centralise the assignment of PHY/NTL/GENID BARs in common code.
> 
> Signed-off-by: Andrew Donnellan <andrew.donnellan at au1.ibm.com>
> ---

That one gave me a headache, mostly because I was not that familiar with 
the bar setup on the nvlink side of things (and some bars are written 
twice!). Hopefully we'll get another pair of eyes with a nvlink focus on 
it. A few questions below.



>   hw/npu2-common.c   |  76 ++++++++++++++++++++++++++++++-
>   hw/npu2-opencapi.c |  80 ++++----------------------------
>   hw/npu2.c          | 116 +++++-----------------------------------------
>   include/npu2.h     |   4 +-
>   4 files changed, 104 insertions(+), 172 deletions(-)
> 
> diff --git a/hw/npu2-common.c b/hw/npu2-common.c
> index 3446acb45bea..b140e9ffd064 100644
> --- a/hw/npu2-common.c
> +++ b/hw/npu2-common.c
> @@ -17,6 +17,7 @@
>   #include <skiboot.h>
>   #include <xscom.h>
>   #include <pci.h>
> +#include <pci-cfg.h>
>   #include <npu2.h>
>   #include <npu2-regs.h>
>   #include <bitutils.h>
> @@ -174,6 +175,79 @@ void npu2_write_bar(struct npu2 *p, struct npu2_bar *bar, uint32_t gcid,
>   	}
>   }
> 
> +static void assign_bars(struct npu2 *npu)
> +{
> +	uint32_t i;
> +	struct npu2_bar *bar;
> +	struct npu2_dev *dev;
> +	struct npu2_bar phy_bars[] = {
> +		/* NPU_REGS must be first in this list */
> +		{ .type = NPU_REGS, .index = 0,
> +		  .reg = NPU2_REG_OFFSET(NPU2_STACK_STCK_0, 0, NPU2_PHY_BAR),
> +		  .enabled = true },
> +		{ .type = NPU_PHY, .index = 0,
> +		  .reg = NPU2_REG_OFFSET(NPU2_STACK_STCK_1, 0, NPU2_PHY_BAR),
> +		  .enabled = true },
> +		{ .type = NPU_PHY, .index = 1,
> +		  .reg = NPU2_REG_OFFSET(NPU2_STACK_STCK_2, 0, NPU2_PHY_BAR),
> +		  .enabled = true },
> +	};
> +	struct npu2_bar last_bar =
> +		{ .type = NPU_GENID, .index = 2,
> +		  .reg = NPU2_REG_OFFSET(NPU2_STACK_STCK_2, 0, NPU2_GENID_BAR) };
> +
> +	/* Set common PHY BARs */
> +	for (i = 0; i < ARRAY_SIZE(phy_bars); i++) {
> +		bar = &phy_bars[i];
> +		npu2_get_bar(npu->chip_id, bar);
> +		npu2_write_bar(npu, bar, npu->chip_id, npu->xscom_base);
> +	}
> +
> +	/* Device BARs */
> +	for (i = 0; i < npu->total_devices; i++) {
> +		dev = &npu->devices[i];
> +		if (dev->type == NPU2_DEV_TYPE_UNKNOWN)
> +			continue;
> +
> +		/* NTL / OCAPI_MMIO BAR */
> +		bar = &dev->ntl_bar;
> +		if (dev->type == NPU2_DEV_TYPE_NVLINK)
> +			bar->type = NPU_NTL;
> +		else if (dev->type == NPU2_DEV_TYPE_OPENCAPI)
> +			bar->type = NPU_OCAPI_MMIO;
> +		bar->index = dev->brick_index;
> +		bar->reg = NPU2_REG_OFFSET(NPU2_STACK_STCK_0 + NPU2DEV_STACK(dev),
> +					   0, NPU2DEV_BRICK(dev) == 0 ?
> +					   NPU2_NTL0_BAR : NPU2_NTL1_BAR);
> +		bar->flags = PCI_CFG_BAR_TYPE_MEM | PCI_CFG_BAR_MEM64;
> +		npu2_get_bar(npu->chip_id, bar);
> +		npu2_write_bar(npu, bar, npu->chip_id, npu->xscom_base);
> +
> +		/* GENID BAR */
> +		bar = &dev->genid_bar;
> +		bar->type = NPU_GENID;
> +		bar->index = NPU2DEV_STACK(dev);
> +		bar->reg = NPU2_REG_OFFSET(NPU2_STACK_STCK_0 + NPU2DEV_STACK(dev),
> +					   0, NPU2_GENID_BAR);
> +		bar->flags = PCI_CFG_BAR_TYPE_MEM | PCI_CFG_BAR_MEM64;
> +		npu2_get_bar(npu->chip_id, bar);
> +		bar->size = 0x10000;
> +		if (NPU2DEV_BRICK(dev))
> +			bar->base += 0x10000;
> +		npu2_write_bar(npu, bar, npu->chip_id, npu->xscom_base);

The GENID reg is per stack (same address for the 2 devices). For 2 
devices on the same stack, isn't the 2nd one overwriting the 1st, with 
only half the size available? I don't understand why we're doing it. And 
it seems different from what we were having for opencapi. I'm guessing 
it may not make much of a difference, since we're only addressing 4k of 
config space.

It matches what nvlink was doing though, but the same comment applies.



> diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c
> index 88e4eb1974a2..b374a1035ac9 100644
> --- a/hw/npu2-opencapi.c
> +++ b/hw/npu2-opencapi.c

> @@ -1582,8 +1530,8 @@ static void setup_device(struct npu2_dev *dev)
>   	uint64_t mm_win[2];
> 
>   	/* Populate PHB device node */
> -	phys_map_get(dev->npu->chip_id, NPU_OCAPI_MMIO, dev->brick_index, &mm_win[0],
> -		     &mm_win[1]);
> +	mm_win[0] = dev->ntl_bar.base;
> +	mm_win[1] = dev->ntl_bar.size;
>   	prlog(PR_DEBUG, "OCAPI: Setting MMIO window to %016llx + %016llx\n",
>   	      mm_win[0], mm_win[1]);
>   	dn_phb = dt_new_addr(dt_root, "pciex", mm_win[0]);
> @@ -1629,7 +1577,8 @@ static void setup_device(struct npu2_dev *dev)
>   	/* Procedure 13.1.3.8 - AFU MMIO Range BARs */
>   	setup_afu_mmio_bars(dev->npu->chip_id, dev->npu->xscom_base, dev);
>   	/* Procedure 13.1.3.9 - AFU Config BARs */
> -	setup_afu_config_bars(dev->npu->chip_id, dev->npu->xscom_base, dev);
> +	dev->genid_bar.enabled = true;
> +	npu2_write_bar(dev->npu, &dev->genid_bar, dev->npu->chip_id, dev->npu->xscom_base);

For readability, I wouldn't mind keeping a separate 
setup_afu_config_bars() function with the (now minimal) genid setup.



More information about the Skiboot mailing list