qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: agraf@suse.de, afaerber@suse.de
Cc: lvivier@redhat.com, thuth@redhat.com,
	Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>,
	aik@ozlabs.ru, qemu-devel@nongnu.org, mdroth@linux.vnet.ibm.com,
	qemu-ppc@nongnu.org, bharata@linux.vnet.ibm.com,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [Qemu-devel] [PATCH 20/27] spapr_pci: enumerate and add PCI device tree
Date: Thu,  2 Jul 2015 16:23:21 +1000	[thread overview]
Message-ID: <1435818208-11808-21-git-send-email-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <1435818208-11808-1-git-send-email-david@gibson.dropbear.id.au>

From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

All the PCI enumeration and device node creation was off-loaded to
SLOF. With PCI hotplug support, code needed to be added to add device
node. This creates multiple copy of the code one in SLOF and other in
hotplug code. To unify this, the patch adds the pci device node
creation in Qemu. For backward compatibility, a flag
"qemu,phb-enumerated" is added to the phb, suggesting to SLOF to not
do device node creation.

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
[ Squashed Michael's drc_index changes ]
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/ppc/spapr_pci.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 133 insertions(+), 17 deletions(-)

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index dc4a683..7c3621c 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -23,6 +23,7 @@
  * THE SOFTWARE.
  */
 #include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
@@ -35,6 +36,7 @@
 #include "qemu/error-report.h"
 #include "qapi/qmp/qerror.h"
 
+#include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/ppc/spapr_drc.h"
 #include "sysemu/device_tree.h"
@@ -966,30 +968,32 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
     return 0;
 }
 
+static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
+                                            PCIDevice *pdev);
+
 /* create OF node for pci device and required OF DT properties */
-static void *spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev,
-                                       int drc_index, const char *drc_name,
-                                       int *dt_offset)
+static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev,
+                                     int drc_index, const char *drc_name,
+                                     void *fdt, int node_offset)
 {
-    void *fdt;
-    int offset, ret, fdt_size;
+    int offset, ret;
     int slot = PCI_SLOT(dev->devfn);
     int func = PCI_FUNC(dev->devfn);
     char nodename[FDT_NAME_MAX];
 
-    fdt = create_device_tree(&fdt_size);
     if (func != 0) {
         snprintf(nodename, FDT_NAME_MAX, "pci@%x,%x", slot, func);
     } else {
         snprintf(nodename, FDT_NAME_MAX, "pci@%x", slot);
     }
-    offset = fdt_add_subnode(fdt, 0, nodename);
+    offset = fdt_add_subnode(fdt, node_offset, nodename);
     ret = spapr_populate_pci_child_dt(dev, fdt, offset, phb->index, drc_index,
                                       drc_name);
     g_assert(!ret);
-
-    *dt_offset = offset;
-    return fdt;
+    if (ret) {
+        return 0;
+    }
+    return offset;
 }
 
 static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
@@ -1002,19 +1006,22 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
     int drc_index = drck->get_index(drc);
     const char *drc_name = drck->get_name(drc);
     void *fdt = NULL;
-    int fdt_start_offset = 0;
+    int fdt_start_offset = 0, fdt_size;
 
-    /* boot-time devices get their device tree node created by SLOF, but for
-     * hotplugged devices we need QEMU to generate it so the guest can fetch
-     * it via RTAS
-     */
     if (dev->hotplugged) {
-        fdt = spapr_create_pci_child_dt(phb, pdev, drc_index, drc_name,
-                                        &fdt_start_offset);
+        fdt = create_device_tree(&fdt_size);
+        fdt_start_offset = spapr_create_pci_child_dt(phb, pdev,
+                                                     drc_index, drc_name,
+                                                     fdt, 0);
+        if (!fdt_start_offset) {
+            error_setg(errp, "Failed to create pci child device tree node");
+            goto out;
+        }
     }
 
     drck->attach(drc, DEVICE(pdev),
                  fdt, fdt_start_offset, !dev->hotplugged, errp);
+out:
     if (*errp) {
         g_free(fdt);
     }
@@ -1056,6 +1063,20 @@ static sPAPRDRConnector *spapr_phb_get_pci_drc(sPAPRPHBState *phb,
                                     pdev->devfn);
 }
 
+static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
+                                            PCIDevice *pdev)
+{
+    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
+    sPAPRDRConnectorClass *drck;
+
+    if (!drc) {
+        return 0;
+    }
+
+    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    return drck->get_index(drc);
+}
+
 static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler,
                                      DeviceState *plugged_dev, Error **errp)
 {
@@ -1480,6 +1501,87 @@ PCIHostState *spapr_create_phb(sPAPRMachineState *spapr, int index)
     return PCI_HOST_BRIDGE(dev);
 }
 
+typedef struct sPAPRFDT {
+    void *fdt;
+    int node_off;
+    sPAPRPHBState *sphb;
+} sPAPRFDT;
+
+static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
+                                          void *opaque)
+{
+    PCIBus *sec_bus;
+    sPAPRFDT *p = opaque;
+    int offset;
+    sPAPRFDT s_fdt;
+    uint32_t drc_index = spapr_phb_get_pci_drc_index(p->sphb, pdev);
+
+    offset = spapr_create_pci_child_dt(p->sphb, pdev,
+                                       drc_index, NULL,
+                                       p->fdt, p->node_off);
+    if (!offset) {
+        error_report("Failed to create pci child device tree node");
+        return;
+    }
+
+    if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=
+         PCI_HEADER_TYPE_BRIDGE)) {
+        return;
+    }
+
+    sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
+    if (!sec_bus) {
+        return;
+    }
+
+    s_fdt.fdt = p->fdt;
+    s_fdt.node_off = offset;
+    s_fdt.sphb = p->sphb;
+    pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+                        spapr_populate_pci_devices_dt,
+                        &s_fdt);
+}
+
+static void spapr_phb_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
+                                           void *opaque)
+{
+    unsigned int *bus_no = opaque;
+    unsigned int primary = *bus_no;
+    unsigned int subordinate = 0xff;
+    PCIBus *sec_bus = NULL;
+
+    if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=
+         PCI_HEADER_TYPE_BRIDGE)) {
+        return;
+    }
+
+    (*bus_no)++;
+    pci_default_write_config(pdev, PCI_PRIMARY_BUS, primary, 1);
+    pci_default_write_config(pdev, PCI_SECONDARY_BUS, *bus_no, 1);
+    pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1);
+
+    sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
+    if (!sec_bus) {
+        return;
+    }
+
+    pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, subordinate, 1);
+    pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+                        spapr_phb_pci_enumerate_bridge, bus_no);
+    pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1);
+}
+
+static void spapr_phb_pci_enumerate(sPAPRPHBState *phb)
+{
+    PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
+    unsigned int bus_no = 0;
+
+    pci_for_each_device(bus, pci_bus_num(bus),
+                        spapr_phb_pci_enumerate_bridge,
+                        &bus_no);
+
+}
+
 int spapr_populate_pci_dt(sPAPRPHBState *phb,
                           uint32_t xics_phandle,
                           void *fdt)
@@ -1519,6 +1621,8 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
         cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
     uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7];
     sPAPRTCETable *tcet;
+    PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
+    sPAPRFDT s_fdt;
 
     /* Start populating the FDT */
     snprintf(nodename, FDT_NAME_MAX, "pci@%" PRIx64, phb->buid);
@@ -1568,6 +1672,18 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
                  tcet->liobn, tcet->bus_offset,
                  tcet->nb_table << tcet->page_shift);
 
+    /* Walk the bridges and program the bus numbers*/
+    spapr_phb_pci_enumerate(phb);
+    _FDT(fdt_setprop_cell(fdt, bus_off, "qemu,phb-enumerated", 0x1));
+
+    /* Populate tree nodes with PCI devices attached */
+    s_fdt.fdt = fdt;
+    s_fdt.node_off = bus_off;
+    s_fdt.sphb = phb;
+    pci_for_each_device(bus, pci_bus_num(bus),
+                        spapr_populate_pci_devices_dt,
+                        &s_fdt);
+
     ret = spapr_drc_populate_dt(fdt, bus_off, OBJECT(phb),
                                 SPAPR_DR_CONNECTOR_TYPE_PCI);
     if (ret) {
-- 
2.4.3

  parent reply	other threads:[~2015-07-02  6:23 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-02  6:23 [Qemu-devel] [PATCH 00/27] sPAPR updates 2015-07-02 David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 01/27] spapr: ensure we have at least one XICS server David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 02/27] pseries: Update SLOF firmware image to qemu-slof-20150429 David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 03/27] spapr: Merge sPAPREnvironment into sPAPRMachineState David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 04/27] spapr: Remove obsolete ram_limit field from sPAPRMachineState David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 05/27] spapr: Remove obsolete entry_point " David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 06/27] spapr: Add sPAPRMachineClass David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 07/27] spapr_pci: encode missing 64-bit memory address space David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 08/27] spapr_pci: encode class code including Prog IF register David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 09/27] spapr_pci: set device node unit address as hex David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 10/27] spapr_iommu: drop erroneous check in h_put_tce_indirect() David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 11/27] spapr_iommu: translate sPAPRTCEAccess to IOMMUAccessFlags David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 12/27] Revert "hw/ppc/spapr_pci.c: Avoid functions not in glib 2.12 (g_hash_table_iter_*)" David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 13/27] spapr: Consider max_cpus during xics initialization David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 14/27] spapr: Support ibm, lrdr-capacity device tree property David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 15/27] cpus: Add a macro to walk CPUs in reverse David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 16/27] spapr: Reorganize CPU dt generation code David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 17/27] spapr: Consolidate cpu init code into a routine David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 18/27] ppc: Update cpu_model in MachineState David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 19/27] xics_kvm: Don't enable KVM_CAP_IRQ_XICS if already enabled David Gibson
2015-07-02  6:23 ` David Gibson [this message]
2015-07-02  6:23 ` [Qemu-devel] [PATCH 21/27] spapr_pci: populate ibm,loc-code David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 22/27] spapr_pci: drop redundant args in spapr_[populate, create]_pci_child_dt David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 23/27] spapr_vty: lookup should only return valid VTY objects David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 24/27] spapr-vty: Use TYPE_ definition instead of hardcoding David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 25/27] sPAPR: Don't enable EEH on emulated PCI devices David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 26/27] sPAPR: Reenable EEH functionality on reboot David Gibson
2015-07-02  6:23 ` [Qemu-devel] [PATCH 27/27] sPAPR: Clear stale MSIx table during EEH reset David Gibson
2015-07-07 12:39 ` [Qemu-devel] [PATCH 00/27] sPAPR updates 2015-07-02 Alexander Graf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1435818208-11808-21-git-send-email-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=afaerber@suse.de \
    --cc=agraf@suse.de \
    --cc=aik@ozlabs.ru \
    --cc=bharata@linux.vnet.ibm.com \
    --cc=lvivier@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=nikunj@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).