diff options
Diffstat (limited to 'hw/pci-host')
-rw-r--r-- | hw/pci-host/pnv_phb.c | 11 | ||||
-rw-r--r-- | hw/pci-host/pnv_phb4_pec.c | 61 |
2 files changed, 64 insertions, 8 deletions
diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index c62b08538a..82332d7a05 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -62,6 +62,15 @@ static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, return true; } +static Object *pnv_phb_user_get_parent(PnvChip *chip, PnvPHB *phb, Error **errp) +{ + if (phb->version == 3) { + return OBJECT(pnv_chip_add_phb(chip, phb)); + } else { + return OBJECT(pnv_pec_add_phb(chip, phb, errp)); + } +} + /* * User created devices won't have the initial setup that default * devices have. This setup consists of assigning a parent device @@ -79,7 +88,7 @@ static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) return false; } - parent = pnv_chip_add_phb(chip, phb, errp); + parent = pnv_phb_user_get_parent(chip, phb, errp); if (!parent) { return false; } diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 43267a428f..3b2850f7a3 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -112,9 +112,50 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, - int stack_no, - Error **errp) +PnvPhb4PecState *pnv_pec_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp) +{ + PnvPhb4PecState *pecs = NULL; + int chip_id = phb->chip_id; + int index = phb->phb_id; + int i, j; + + if (phb->version == 4) { + Pnv9Chip *chip9 = PNV9_CHIP(chip); + + pecs = chip9->pecs; + } else if (phb->version == 5) { + Pnv10Chip *chip10 = PNV10_CHIP(chip); + + pecs = chip10->pecs; + } else { + g_assert_not_reached(); + } + + for (i = 0; i < chip->num_pecs; i++) { + /* + * For each PEC, check the amount of phbs it supports + * and see if the given phb4 index matches an index. + */ + PnvPhb4PecState *pec = &pecs[i]; + + for (j = 0; j < pec->num_phbs; j++) { + if (index == pnv_phb4_pec_get_phb_id(pec, j)) { + pec->phbs[j] = phb; + phb->pec = pec; + return pec; + } + } + } + error_setg(errp, + "pnv-phb4 chip-id %d index %d didn't match any existing PEC", + chip_id, index); + + return NULL; +} + +static PnvPHB *pnv_pec_default_phb_realize(PnvPhb4PecState *pec, + int stack_no, + Error **errp) { PnvPHB *phb = PNV_PHB(qdev_new(TYPE_PNV_PHB)); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); @@ -128,8 +169,9 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, &error_fatal); if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { - return; + return NULL; } + return phb; } static void pnv_pec_realize(DeviceState *dev, Error **errp) @@ -148,8 +190,9 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) /* Create PHBs if running with defaults */ if (defaults_enabled()) { + g_assert(pec->num_phbs <= MAX_PHBS_PER_PEC); for (i = 0; i < pec->num_phbs; i++) { - pnv_pec_default_phb_realize(pec, i, errp); + pec->phbs[i] = pnv_pec_default_phb_realize(pec, i, errp); } } @@ -197,9 +240,12 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, pecc->compat_size))); for (i = 0; i < pec->num_phbs; i++) { - int phb_id = pnv_phb4_pec_get_phb_id(pec, i); int stk_offset; + if (!pec->phbs[i]) { + continue; + } + name = g_strdup_printf("stack@%x", i); stk_offset = fdt_add_subnode(fdt, offset, name); _FDT(stk_offset); @@ -207,7 +253,8 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat, pecc->stk_compat_size))); _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i))); - _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb_id))); + _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", + pec->phbs[i]->phb_id))); } return 0; |