From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
To: Thomas Huth <thuth@redhat.com>
Cc: qemu-devel@nongnu.org, aik@ozlabs.ru, agraf@suse.de,
mdroth@linux.vnet.ibm.com, qemu-ppc@nongnu.org,
david@gibson.dropbear.id.au
Subject: Re: [Qemu-devel] [PATCH v3 4/6] spapr_pci: enumerate and add PCI device tree
Date: Wed, 06 May 2015 11:26:25 +0530 [thread overview]
Message-ID: <87mw1ijlkm.fsf@linux.vnet.ibm.com> (raw)
In-Reply-To: <20150505173232.42398ece@thh440s>
Thomas Huth <thuth@redhat.com> writes:
> On Tue, 5 May 2015 14:23:54 +0530
> Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> wrote:
>
>> 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>
>> ---
>> hw/ppc/spapr_pci.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 103 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>> index 8b02a3e..103284a 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"
>> @@ -945,7 +947,10 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
>> * processed by OF beforehand
>> */
>> _FDT(fdt_setprop_string(fdt, offset, "name", "pci"));
>> - _FDT(fdt_setprop(fdt, offset, "ibm,loc-code", drc_name, strlen(drc_name)));
>> + if (drc_name) {
>> + _FDT(fdt_setprop(fdt, offset, "ibm,loc-code", drc_name,
>> + strlen(drc_name)));
>> + }
>> _FDT(fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index));
>>
>> _FDT(fdt_setprop_cell(fdt, offset, "#address-cells",
>> @@ -1001,10 +1006,6 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>> void *fdt = NULL;
>> int fdt_start_offset = 0;
>>
>> - /* 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);
>> @@ -1482,6 +1483,89 @@ PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
>> return PCI_HOST_BRIDGE(dev);
>> }
>>
>> +typedef struct sPAPRFDT {
>> + void *fdt;
>> + int node_off;
>> + uint32_t index;
>> +} sPAPRFDT;
>> +
>> +static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
>> + void *opaque)
>> +{
>> + PCIBus *sec_bus;
>> + sPAPRFDT *p = opaque;
>> + int ret, offset;
>> + int slot = PCI_SLOT(pdev->devfn);
>> + int func = PCI_FUNC(pdev->devfn);
>> + char nodename[512];
>
> That's quite a big array ....
>
>> + sPAPRFDT s_fdt;
>> +
>> + if (func) {
>> + sprintf(nodename, "pci@%d,%d", slot, func);
>> + } else {
>> + sprintf(nodename, "pci@%d", slot);
>> + }
>
> ... just for holding such a small string. Could you maybe use
> a smaller array size for nodename (especially since you call this
> function recursively)?
Sure, will change this to 32 bytes, that should be sufficient.
>
>> + offset = fdt_add_subnode(p->fdt, p->node_off, nodename);
>> + ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->index, 0, NULL);
>
> The above code sequence looks pretty much similar to
> spapr_create_pci_child_dt() ... maybe it's worth the effort to merge
> the common code of both functions into a separate helper function
> to avoid the duplication? ... not sure if this is worth the effort,
> it's just a suggestion.
I had thought about it earlier but something was not matching. Let me
have a relook, things have changed.
>
>> + g_assert(!ret);
>
> You know that assert statements can simply be disabled by a
> preprocessor switch - and in that case there is no more error handling
> here at all and the code continues silently with a partial initialized
> node!
Thanks for bringing this to notice, assert() ?
> So it's maybe better to do a proper error handling here instead?
Will change this error handling here.
>
>> + 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.index = p->index;
>> + 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 short *bus_no = (unsigned short *) opaque;
>
> opaque is a void pointer, so I think you don't need the typecast here.
Ok, QEMU has strong type checking, so by default I typecast them every time.
>
>> + unsigned short primary = *bus_no;
>> + unsigned short secondary;
>> + unsigned short subordinate = 0xff;
>
> Is there a special reason for using unsigned short variables here?
No special reason, actually unsigned char should do, as the max is bus
number can only be 255
> "unsigned int" would sound much more natural to me.
>
>> + if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) ==
>> + PCI_HEADER_TYPE_BRIDGE)) {
>> + PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
>> + secondary = *bus_no + 1;
>> + pci_default_write_config(pdev, PCI_PRIMARY_BUS, primary, 1);
>> + pci_default_write_config(pdev, PCI_SECONDARY_BUS, secondary, 1);
>> + pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, secondary, 1);
>> + *bus_no = *bus_no + 1;
>> + if (sec_bus) {
>> + pci_default_write_config(pdev, PCI_PRIMARY_BUS, primary, 1);
>> + pci_default_write_config(pdev, PCI_SECONDARY_BUS, secondary, 1);
>> + pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, subordinate, 1);
>
> You write all value here again ... I think you c\ould either drop the
> write to the PRIMARY and SECONDARY BUS registers, or you could use a
> proper if-else instead.
I will drop the PRIMARY and SECONDARY here, that would do.
>
>> + 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 short bus_no = 0;
>
> Again, why "short" ?
>
>> + 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)
>> @@ -1521,6 +1605,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 */
>> sprintf(nodename, "pci@%" PRIx64, phb->buid);
>> @@ -1570,6 +1656,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.index = phb->index;
>> + 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) {
>
> Thomas
Regards
Nikunj
next prev parent reply other threads:[~2015-05-06 5:56 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-05 8:53 [Qemu-devel] [PATCH v3 0/6] spapr_pci: DT field fixes and PCI DT node creation in QEMU Nikunj A Dadhania
2015-05-05 8:53 ` [Qemu-devel] [PATCH v3 1/6] spapr_pci: remove duplicate macros Nikunj A Dadhania
2015-05-05 13:53 ` Thomas Huth
2015-05-06 5:41 ` Nikunj A Dadhania
2015-05-07 0:55 ` David Gibson
2015-05-07 4:55 ` Nikunj A Dadhania
2015-05-05 8:53 ` [Qemu-devel] [PATCH v3 2/6] spapr_pci: encode missing 64-bit memory address space Nikunj A Dadhania
2015-05-05 14:28 ` Thomas Huth
2015-05-06 5:44 ` Nikunj A Dadhania
2015-05-06 7:01 ` Thomas Huth
2015-05-06 8:23 ` Nikunj A Dadhania
2015-05-05 8:53 ` [Qemu-devel] [PATCH v3 3/6] spapr_pci: encode class code including Prog IF register Nikunj A Dadhania
2015-05-05 12:55 ` David Gibson
2015-05-05 14:50 ` Thomas Huth
2015-05-05 8:53 ` [Qemu-devel] [PATCH v3 4/6] spapr_pci: enumerate and add PCI device tree Nikunj A Dadhania
2015-05-05 15:32 ` Thomas Huth
2015-05-06 5:56 ` Nikunj A Dadhania [this message]
2015-05-05 8:53 ` [Qemu-devel] [PATCH v3 5/6] spapr_pci: fix boot-time device tree fields for pci hotplug Nikunj A Dadhania
2015-05-05 13:09 ` David Gibson
2015-05-06 5:57 ` Nikunj A Dadhania
2015-05-05 8:53 ` [Qemu-devel] [PATCH v3 6/6] spapr_pci: populate ibm,loc-code Nikunj A Dadhania
2015-05-05 16:03 ` Thomas Huth
2015-05-06 6:14 ` Nikunj A Dadhania
2015-05-07 0:32 ` David Gibson
2015-05-07 4:56 ` Nikunj A Dadhania
-- strict thread matches above, loose matches on Subject: below --
2015-05-05 8:43 [Qemu-devel] [PATCH v3 0/6] spapr_pci: DT field fixes and PCI DT node creation in QEMU Nikunj A Dadhania
2015-05-05 8:43 ` [Qemu-devel] [PATCH v3 4/6] spapr_pci: enumerate and add PCI device tree Nikunj A Dadhania
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=87mw1ijlkm.fsf@linux.vnet.ibm.com \
--to=nikunj@linux.vnet.ibm.com \
--cc=agraf@suse.de \
--cc=aik@ozlabs.ru \
--cc=david@gibson.dropbear.id.au \
--cc=mdroth@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.