Reserve 32 entries of type PCI in each PHB's initial FDT. This advertises to guests that each PHB is DR-capable device with physical hotpluggable slots. This is necessary for allowing hotplugging of devices to it later via bus rescan or guest rpaphp hotplug module.
Each entry is assigned a name of "Slot <<bus_idx>*32 +1>", advertised as a hotpluggable PCI slot, and assigned to power domain -1 to indicate to the guest that power management is handled by the hardware. This models a DR-capable PCI expansion device attached to a host/lpar via a single PHB with 32 physical hotpluggable slots (as opposed to a virtual bridge device with external management console). Hotplug will be handled by the guest via bus rescan or the rpaphp hotplug module. Signed-off-by: Michael Roth <mdr...@linux.vnet.ibm.com> --- hw/ppc/spapr.c | 3 +- hw/ppc/spapr_pci.c | 101 +++++++++++++++++++++++++++++++++++++++++++ include/hw/pci-host/spapr.h | 1 + 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ec3ba43..0607559 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -739,7 +739,8 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, QLIST_FOREACH(phb, &spapr->phbs, list) { drc_entry = spapr_add_phb_to_drc_table(phb->buid, 2 /* Unusable */); g_assert(drc_entry); - ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); + ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, drc_entry->drc_index, + fdt); } if (ret < 0) { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 5eb6852..4a88212 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1041,8 +1041,103 @@ PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index) #define b_fff(x) b_x((x), 8, 3) /* function number */ #define b_rrrrrrrr(x) b_x((x), 0, 8) /* register number */ +static void spapr_create_drc_phb_dt_entries(void *fdt, int bus_off, int phb_index) +{ + char char_buf[1024]; + uint32_t int_buf[SPAPR_DRC_PHB_SLOT_MAX + 1]; + uint32_t *entries; + int i, ret, offset; + + /* ibm,drc-indexes */ + memset(int_buf, 0 , sizeof(int_buf)); + int_buf[0] = SPAPR_DRC_PHB_SLOT_MAX; + + for (i = 1; i <= SPAPR_DRC_PHB_SLOT_MAX; i++) { + int_buf[i] = SPAPR_DRC_DEV_ID_BASE + (phb_index << 8) + ((i - 1) << 3); + } + + ret = fdt_setprop(fdt, bus_off, "ibm,drc-indexes", int_buf, + sizeof(int_buf)); + if (ret) { + g_warning("error adding 'ibm,drc-indexes' field for PHB FDT"); + } + + /* ibm,drc-power-domains */ + memset(int_buf, 0, sizeof(int_buf)); + int_buf[0] = SPAPR_DRC_PHB_SLOT_MAX; + + for (i = 1; i <= SPAPR_DRC_PHB_SLOT_MAX; i++) { + int_buf[i] = 0xffffffff; + } + + ret = fdt_setprop(fdt, bus_off, "ibm,drc-power-domains", int_buf, + sizeof(int_buf)); + if (ret) { + g_warning("error adding 'ibm,drc-power-domains' field for PHB FDT"); + } + + /* ibm,drc-names */ + memset(char_buf, 0, sizeof(char_buf)); + entries = (uint32_t *)&char_buf[0]; + *entries = SPAPR_DRC_PHB_SLOT_MAX; + offset = sizeof(*entries); + + for (i = 1; i <= SPAPR_DRC_PHB_SLOT_MAX; i++) { + offset += sprintf(char_buf + offset, "Slot %d", + (phb_index * SPAPR_DRC_PHB_SLOT_MAX) + i - 1); + char_buf[offset++] = '\0'; + } + + ret = fdt_setprop(fdt, bus_off, "ibm,drc-names", char_buf, offset); + if (ret) { + g_warning("error adding 'ibm,drc-names' field for PHB FDT"); + } + + /* ibm,drc-types */ + memset(char_buf, 0, sizeof(char_buf)); + entries = (uint32_t *)&char_buf[0]; + *entries = SPAPR_DRC_PHB_SLOT_MAX; + offset = sizeof(*entries); + + for (i = 0; i < SPAPR_DRC_PHB_SLOT_MAX; i++) { + offset += sprintf(char_buf + offset, "28"); + char_buf[offset++] = '\0'; + } + + ret = fdt_setprop(fdt, bus_off, "ibm,drc-types", char_buf, offset); + if (ret) { + g_warning("error adding 'ibm,drc-types' field for PHB FDT"); + } + + /* we want the initial indicator state to be 0 - "empty", when we + * hot-plug an adaptor in the slot, we need to set the indicator + * to 1 - "present." + */ + + /* ibm,indicator-9003 */ + memset(int_buf, 0, sizeof(int_buf)); + int_buf[0] = SPAPR_DRC_PHB_SLOT_MAX; + + ret = fdt_setprop(fdt, bus_off, "ibm,indicator-9003", int_buf, + sizeof(int_buf)); + if (ret) { + g_warning("error adding 'ibm,indicator-9003' field for PHB FDT"); + } + + /* ibm,sensor-9003 */ + memset(int_buf, 0, sizeof(int_buf)); + int_buf[0] = SPAPR_DRC_PHB_SLOT_MAX; + + ret = fdt_setprop(fdt, bus_off, "ibm,sensor-9003", int_buf, + sizeof(int_buf)); + if (ret) { + g_warning("error adding 'ibm,sensor-9003' field for PHB FDT"); + } +} + int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, + uint32_t drc_index, void *fdt) { int bus_off, i, j; @@ -1124,6 +1219,12 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, phb->dma_liobn, phb->dma_window_start, phb->dma_window_size); + spapr_create_drc_phb_dt_entries(fdt, bus_off, phb->index); + if (drc_index) { + _FDT(fdt_setprop(fdt, bus_off, "ibm,my-drc-index", &drc_index, + sizeof(drc_index))); + } + return 0; } diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 970b4a9..43d19a5 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -86,6 +86,7 @@ PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index); int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, + uint32_t drc_index, void *fdt); void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr); -- 1.7.9.5