diff mbox

[v3,6/6] spapr_pci: populate ibm,loc-code

Message ID 1430816036-26408-7-git-send-email-nikunj@linux.vnet.ibm.com
State New
Headers show

Commit Message

Nikunj A Dadhania May 5, 2015, 8:53 a.m. UTC
Each hardware instance has a platform unique location code.  The OF
device tree that describes a part of a hardware entity must include
the “ibm,loc-code” property with a value that represents the location
code for that hardware entity.

Populate ibm,loc-code.
1) PCI passthru devices need to identify with its own ibm,loc-code
   available on the host.
2) Emulated devices encode as following:
   qemu_<name>:<phb-index>:<slot>.<fn>

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 hw/ppc/spapr_pci.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 75 insertions(+), 11 deletions(-)

Comments

Thomas Huth May 5, 2015, 4:03 p.m. UTC | #1
On Tue,  5 May 2015 14:23:56 +0530
Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> wrote:

> Each hardware instance has a platform unique location code.  The OF
> device tree that describes a part of a hardware entity must include
> the “ibm,loc-code” property with a value that represents the location
> code for that hardware entity.
> 
> Populate ibm,loc-code.
> 1) PCI passthru devices need to identify with its own ibm,loc-code
>    available on the host.
> 2) Emulated devices encode as following:
>    qemu_<name>:<phb-index>:<slot>.<fn>
> 
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  hw/ppc/spapr_pci.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 75 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index cbd5661..eacf0bd 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -744,6 +744,70 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>      return &phb->iommu_as;
>  }
>  
> +static bool spapr_phb_vfio_get_devspec_value(PCIDevice *pdev, char **value)
> +{
> +    char *host;
> +    char path[PATH_MAX];
> +
> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
> +    if (!host) {
> +        return false;
> +    }
> +
> +    snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/devspec", host);
> +    g_free(host);
> +
> +    return g_file_get_contents(path, value, NULL, NULL);
> +}
> +
> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> +{
> +    char path[PATH_MAX], *buf = NULL;
> +
> +    /* We have a vfio host bridge lets get the path. */
> +    if (!spapr_phb_vfio_get_devspec_value(pdev, &buf)) {
> +        return NULL;
> +    }
> +
> +    snprintf(path, sizeof(path), "/proc/device-tree%s/ibm,loc-code", buf);
> +    g_free(buf);
> +
> +    if (g_file_get_contents(path, &buf, NULL, NULL)) {
> +        return buf;
> +    } else {
> +        return NULL;
> +    }

Minor idea for an optimization: g_file_get_contents() should set buf to
NULL in case of errors anyway, so you could omit the "if" and
"return NULLL" and simply always "return buf" here.

> +}
> +
> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> +{
> +    char *path = g_malloc(PATH_MAX);
> +
> +    if (!path) {
> +        return NULL;
> +    }
> +
> +    /*
> +     * For non-vfio devices and failures make up the location code out

This comment ("and failures") ...

> +     * of the name, slot and function.
> +     *
> +     *       qemu_<name>:<phb-index>:<slot>.<fn>
> +     */
> +    snprintf(path, PATH_MAX, "qemu_%s:%02d:%02d.%1d", pdev->name,
> +             sphb->index, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
> +    return path;
> +}
> +
> +
> +static char *spapr_ibm_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
> +{
> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci") != NULL) {
> +        return spapr_phb_vfio_get_loc_code(sphb, pdev);
> +    } else {
> +        return spapr_phb_get_loc_code(sphb, pdev);
> +    }

... does not match quite the behavior here, as far as I can see. I
guess you also wanted to fall back to spapr_phb_get_loc_code() in case 
spapr_phb_vfio_get_loc_code() did not work as expected (eg. when the
access to the /sys or /proc filesystem failed)?

> +}
> +
>  /* Macros to operate with address in OF binding to PCI */
>  #define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
>  #define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
> @@ -881,12 +945,12 @@ static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
>  }
>  
>  static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
> -                                       int phb_index, int drc_index,
> -                                       const char *drc_name)
> +                                       sPAPRPHBState *phb, int drc_index)

As David already noted, the sPAPRPHBState related hunks likely rather
belong to an earlier patch already?

 Thomas
Nikunj A Dadhania May 6, 2015, 6:14 a.m. UTC | #2
Thomas Huth <thuth@redhat.com> writes:

> On Tue,  5 May 2015 14:23:56 +0530
> Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> wrote:
>
>> Each hardware instance has a platform unique location code.  The OF
>> device tree that describes a part of a hardware entity must include
>> the “ibm,loc-code” property with a value that represents the location
>> code for that hardware entity.
>> 
>> Populate ibm,loc-code.
>> 1) PCI passthru devices need to identify with its own ibm,loc-code
>>    available on the host.
>> 2) Emulated devices encode as following:
>>    qemu_<name>:<phb-index>:<slot>.<fn>
>> 
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>> ---
>>  hw/ppc/spapr_pci.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-------
>>  1 file changed, 75 insertions(+), 11 deletions(-)
>> 
>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>> index cbd5661..eacf0bd 100644
>> --- a/hw/ppc/spapr_pci.c
>> +++ b/hw/ppc/spapr_pci.c
>> @@ -744,6 +744,70 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>>      return &phb->iommu_as;
>>  }
>>  
>> +static bool spapr_phb_vfio_get_devspec_value(PCIDevice *pdev, char **value)
>> +{
>> +    char *host;
>> +    char path[PATH_MAX];
>> +
>> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
>> +    if (!host) {
>> +        return false;
>> +    }
>> +
>> +    snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/devspec", host);
>> +    g_free(host);
>> +
>> +    return g_file_get_contents(path, value, NULL, NULL);
>> +}
>> +
>> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>> +{
>> +    char path[PATH_MAX], *buf = NULL;
>> +
>> +    /* We have a vfio host bridge lets get the path. */
>> +    if (!spapr_phb_vfio_get_devspec_value(pdev, &buf)) {
>> +        return NULL;
>> +    }
>> +
>> +    snprintf(path, sizeof(path), "/proc/device-tree%s/ibm,loc-code", buf);
>> +    g_free(buf);
>> +
>> +    if (g_file_get_contents(path, &buf, NULL, NULL)) {
>> +        return buf;
>> +    } else {
>> +        return NULL;
>> +    }
>
> Minor idea for an optimization: g_file_get_contents() should set buf to
> NULL in case of errors anyway, so you could omit the "if" and
> "return NULLL" and simply always "return buf" here.

Sure

>
>> +}
>> +
>> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>> +{
>> +    char *path = g_malloc(PATH_MAX);
>> +
>> +    if (!path) {
>> +        return NULL;
>> +    }
>> +
>> +    /*
>> +     * For non-vfio devices and failures make up the location code out
>
> This comment ("and failures") ...

Oh right, one option is to drop that...

>
>> +     * of the name, slot and function.
>> +     *
>> +     *       qemu_<name>:<phb-index>:<slot>.<fn>
>> +     */
>> +    snprintf(path, PATH_MAX, "qemu_%s:%02d:%02d.%1d", pdev->name,
>> +             sphb->index, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
>> +    return path;
>> +}
>> +
>> +
>> +static char *spapr_ibm_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
>> +{
>> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci") != NULL) {
>> +        return spapr_phb_vfio_get_loc_code(sphb, pdev);
>> +    } else {
>> +        return spapr_phb_get_loc_code(sphb, pdev);
>> +    }
>
> ... does not match quite the behavior here, as far as I can see. I
> guess you also wanted to fall back to spapr_phb_get_loc_code() in case 
> spapr_phb_vfio_get_loc_code() did not work as expected (eg. when the
> access to the /sys or /proc filesystem failed)?

... In current case, if getting vfio device loc_code fails, we would not
 add any ibm,loc_code info. I thought that would be the proper
 behaviour. As "qemu_" would indicate it as an emulated device, which is
 not true. Or encode it as follows:

"vfio_<name>:<phb-index>:<slot>.<fn>"

So more checks would be needed here in that case:

if (vfio) {
   buf = vfio_get_loc_code()
   if (!buf) 
      buf = cook_vfio_get_loc_code()
   return buf;
} else { ... }

>
>> +}
>> +
>>  /* Macros to operate with address in OF binding to PCI */
>>  #define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
>>  #define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
>> @@ -881,12 +945,12 @@ static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
>>  }
>>  
>>  static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
>> -                                       int phb_index, int drc_index,
>> -                                       const char *drc_name)
>> +                                       sPAPRPHBState *phb, int drc_index)
>
> As David already noted, the sPAPRPHBState related hunks likely rather
> belong to an earlier patch already?

Yes, I will take care, this resuled while juggling with the patches :-)

Regards
Nikunj
David Gibson May 7, 2015, 12:32 a.m. UTC | #3
On Wed, May 06, 2015 at 11:44:59AM +0530, Nikunj A Dadhania wrote:
> Thomas Huth <thuth@redhat.com> writes:
> 
> > On Tue,  5 May 2015 14:23:56 +0530
> > Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> wrote:
> >
> >> Each hardware instance has a platform unique location code.  The OF
> >> device tree that describes a part of a hardware entity must include
> >> the “ibm,loc-code” property with a value that represents the location
> >> code for that hardware entity.
> >> 
> >> Populate ibm,loc-code.
> >> 1) PCI passthru devices need to identify with its own ibm,loc-code
> >>    available on the host.
> >> 2) Emulated devices encode as following:
> >>    qemu_<name>:<phb-index>:<slot>.<fn>
> >> 
> >> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> >> ---
> >>  hw/ppc/spapr_pci.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-------
> >>  1 file changed, 75 insertions(+), 11 deletions(-)
> >> 
> >> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> >> index cbd5661..eacf0bd 100644
> >> --- a/hw/ppc/spapr_pci.c
> >> +++ b/hw/ppc/spapr_pci.c
> >> @@ -744,6 +744,70 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
> >>      return &phb->iommu_as;
> >>  }
> >>  
> >> +static bool spapr_phb_vfio_get_devspec_value(PCIDevice *pdev, char **value)
> >> +{
> >> +    char *host;
> >> +    char path[PATH_MAX];
> >> +
> >> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
> >> +    if (!host) {
> >> +        return false;
> >> +    }
> >> +
> >> +    snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/devspec", host);
> >> +    g_free(host);
> >> +
> >> +    return g_file_get_contents(path, value, NULL, NULL);
> >> +}
> >> +
> >> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> >> +{
> >> +    char path[PATH_MAX], *buf = NULL;
> >> +
> >> +    /* We have a vfio host bridge lets get the path. */
> >> +    if (!spapr_phb_vfio_get_devspec_value(pdev, &buf)) {
> >> +        return NULL;
> >> +    }
> >> +
> >> +    snprintf(path, sizeof(path), "/proc/device-tree%s/ibm,loc-code", buf);
> >> +    g_free(buf);
> >> +
> >> +    if (g_file_get_contents(path, &buf, NULL, NULL)) {
> >> +        return buf;
> >> +    } else {
> >> +        return NULL;
> >> +    }
> >
> > Minor idea for an optimization: g_file_get_contents() should set buf to
> > NULL in case of errors anyway, so you could omit the "if" and
> > "return NULLL" and simply always "return buf" here.
> 
> Sure
> 
> >
> >> +}
> >> +
> >> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> >> +{
> >> +    char *path = g_malloc(PATH_MAX);
> >> +
> >> +    if (!path) {
> >> +        return NULL;
> >> +    }
> >> +
> >> +    /*
> >> +     * For non-vfio devices and failures make up the location code out
> >
> > This comment ("and failures") ...
> 
> Oh right, one option is to drop that...
> 
> >
> >> +     * of the name, slot and function.
> >> +     *
> >> +     *       qemu_<name>:<phb-index>:<slot>.<fn>
> >> +     */
> >> +    snprintf(path, PATH_MAX, "qemu_%s:%02d:%02d.%1d", pdev->name,
> >> +             sphb->index, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
> >> +    return path;
> >> +}
> >> +
> >> +
> >> +static char *spapr_ibm_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
> >> +{
> >> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci") != NULL) {
> >> +        return spapr_phb_vfio_get_loc_code(sphb, pdev);
> >> +    } else {
> >> +        return spapr_phb_get_loc_code(sphb, pdev);
> >> +    }
> >
> > ... does not match quite the behavior here, as far as I can see. I
> > guess you also wanted to fall back to spapr_phb_get_loc_code() in case 
> > spapr_phb_vfio_get_loc_code() did not work as expected (eg. when the
> > access to the /sys or /proc filesystem failed)?
> 
> ... In current case, if getting vfio device loc_code fails, we would not
>  add any ibm,loc_code info. I thought that would be the proper
>  behaviour. As "qemu_" would indicate it as an emulated device, which is
>  not true. Or encode it as follows:
> 
> "vfio_<name>:<phb-index>:<slot>.<fn>"
> 
> So more checks would be needed here in that case:
> 
> if (vfio) {
>    buf = vfio_get_loc_code()
>    if (!buf) 
>       buf = cook_vfio_get_loc_code()
>    return buf;
> } else { ... }

If you can't determine the loc code, I think just leaving it out is
probably the best option for now.  We can add fancier fallbacks in
future if they seem like they make sense.
Nikunj A Dadhania May 7, 2015, 4:56 a.m. UTC | #4
David Gibson <david@gibson.dropbear.id.au> writes:

> On Wed, May 06, 2015 at 11:44:59AM +0530, Nikunj A Dadhania wrote:
>> Thomas Huth <thuth@redhat.com> writes:
>> 
>> > On Tue,  5 May 2015 14:23:56 +0530
>> > Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> wrote:
>> >
>> >> Each hardware instance has a platform unique location code.  The OF
>> >> device tree that describes a part of a hardware entity must include
>> >> the “ibm,loc-code” property with a value that represents the location
>> >> code for that hardware entity.
>> >> 
>> >> Populate ibm,loc-code.
>> >> 1) PCI passthru devices need to identify with its own ibm,loc-code
>> >>    available on the host.
>> >> 2) Emulated devices encode as following:
>> >>    qemu_<name>:<phb-index>:<slot>.<fn>
>> >> 
>> >> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>> >> ---
>> >>  hw/ppc/spapr_pci.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-------
>> >>  1 file changed, 75 insertions(+), 11 deletions(-)
>> >> 
>> >> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>> >> index cbd5661..eacf0bd 100644
>> >> --- a/hw/ppc/spapr_pci.c
>> >> +++ b/hw/ppc/spapr_pci.c
>> >> @@ -744,6 +744,70 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>> >>      return &phb->iommu_as;
>> >>  }
>> >>  
>> >> +static bool spapr_phb_vfio_get_devspec_value(PCIDevice *pdev, char **value)
>> >> +{
>> >> +    char *host;
>> >> +    char path[PATH_MAX];
>> >> +
>> >> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
>> >> +    if (!host) {
>> >> +        return false;
>> >> +    }
>> >> +
>> >> +    snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/devspec", host);
>> >> +    g_free(host);
>> >> +
>> >> +    return g_file_get_contents(path, value, NULL, NULL);
>> >> +}
>> >> +
>> >> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>> >> +{
>> >> +    char path[PATH_MAX], *buf = NULL;
>> >> +
>> >> +    /* We have a vfio host bridge lets get the path. */
>> >> +    if (!spapr_phb_vfio_get_devspec_value(pdev, &buf)) {
>> >> +        return NULL;
>> >> +    }
>> >> +
>> >> +    snprintf(path, sizeof(path), "/proc/device-tree%s/ibm,loc-code", buf);
>> >> +    g_free(buf);
>> >> +
>> >> +    if (g_file_get_contents(path, &buf, NULL, NULL)) {
>> >> +        return buf;
>> >> +    } else {
>> >> +        return NULL;
>> >> +    }
>> >
>> > Minor idea for an optimization: g_file_get_contents() should set buf to
>> > NULL in case of errors anyway, so you could omit the "if" and
>> > "return NULLL" and simply always "return buf" here.
>> 
>> Sure
>> 
>> >
>> >> +}
>> >> +
>> >> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>> >> +{
>> >> +    char *path = g_malloc(PATH_MAX);
>> >> +
>> >> +    if (!path) {
>> >> +        return NULL;
>> >> +    }
>> >> +
>> >> +    /*
>> >> +     * For non-vfio devices and failures make up the location code out
>> >
>> > This comment ("and failures") ...
>> 
>> Oh right, one option is to drop that...
>> 
>> >
>> >> +     * of the name, slot and function.
>> >> +     *
>> >> +     *       qemu_<name>:<phb-index>:<slot>.<fn>
>> >> +     */
>> >> +    snprintf(path, PATH_MAX, "qemu_%s:%02d:%02d.%1d", pdev->name,
>> >> +             sphb->index, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
>> >> +    return path;
>> >> +}
>> >> +
>> >> +
>> >> +static char *spapr_ibm_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
>> >> +{
>> >> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci") != NULL) {
>> >> +        return spapr_phb_vfio_get_loc_code(sphb, pdev);
>> >> +    } else {
>> >> +        return spapr_phb_get_loc_code(sphb, pdev);
>> >> +    }
>> >
>> > ... does not match quite the behavior here, as far as I can see. I
>> > guess you also wanted to fall back to spapr_phb_get_loc_code() in case 
>> > spapr_phb_vfio_get_loc_code() did not work as expected (eg. when the
>> > access to the /sys or /proc filesystem failed)?
>> 
>> ... In current case, if getting vfio device loc_code fails, we would not
>>  add any ibm,loc_code info. I thought that would be the proper
>>  behaviour. As "qemu_" would indicate it as an emulated device, which is
>>  not true. Or encode it as follows:
>> 
>> "vfio_<name>:<phb-index>:<slot>.<fn>"
>> 
>> So more checks would be needed here in that case:
>> 
>> if (vfio) {
>>    buf = vfio_get_loc_code()
>>    if (!buf) 
>>       buf = cook_vfio_get_loc_code()
>>    return buf;
>> } else { ... }
>
> If you can't determine the loc code, I think just leaving it out is
> probably the best option for now.  We can add fancier fallbacks in
> future if they seem like they make sense.

I already have the fancy version now, will send it for review.

Regards
Nikunj
diff mbox

Patch

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index cbd5661..eacf0bd 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -744,6 +744,70 @@  static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
     return &phb->iommu_as;
 }
 
+static bool spapr_phb_vfio_get_devspec_value(PCIDevice *pdev, char **value)
+{
+    char *host;
+    char path[PATH_MAX];
+
+    host = object_property_get_str(OBJECT(pdev), "host", NULL);
+    if (!host) {
+        return false;
+    }
+
+    snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/devspec", host);
+    g_free(host);
+
+    return g_file_get_contents(path, value, NULL, NULL);
+}
+
+static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
+{
+    char path[PATH_MAX], *buf = NULL;
+
+    /* We have a vfio host bridge lets get the path. */
+    if (!spapr_phb_vfio_get_devspec_value(pdev, &buf)) {
+        return NULL;
+    }
+
+    snprintf(path, sizeof(path), "/proc/device-tree%s/ibm,loc-code", buf);
+    g_free(buf);
+
+    if (g_file_get_contents(path, &buf, NULL, NULL)) {
+        return buf;
+    } else {
+        return NULL;
+    }
+}
+
+static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
+{
+    char *path = g_malloc(PATH_MAX);
+
+    if (!path) {
+        return NULL;
+    }
+
+    /*
+     * For non-vfio devices and failures make up the location code out
+     * of the name, slot and function.
+     *
+     *       qemu_<name>:<phb-index>:<slot>.<fn>
+     */
+    snprintf(path, PATH_MAX, "qemu_%s:%02d:%02d.%1d", pdev->name,
+             sphb->index, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+    return path;
+}
+
+
+static char *spapr_ibm_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
+{
+    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci") != NULL) {
+        return spapr_phb_vfio_get_loc_code(sphb, pdev);
+    } else {
+        return spapr_phb_get_loc_code(sphb, pdev);
+    }
+}
+
 /* Macros to operate with address in OF binding to PCI */
 #define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
 #define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
@@ -881,12 +945,12 @@  static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
 }
 
 static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
-                                       int phb_index, int drc_index,
-                                       const char *drc_name)
+                                       sPAPRPHBState *phb, int drc_index)
 {
     ResourceProps rp;
     bool is_bridge = false;
     int pci_status;
+    char *buf = NULL;
 
     if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
         PCI_HEADER_TYPE_BRIDGE) {
@@ -947,9 +1011,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"));
-    if (drc_name) {
-        _FDT(fdt_setprop(fdt, offset, "ibm,loc-code", drc_name,
-                         strlen(drc_name)));
+    buf = spapr_ibm_get_loc_code(phb, dev);
+    if (buf) {
+        _FDT(fdt_setprop_string(fdt, offset, "ibm,loc-code", buf));
+        g_free(buf);
     }
     if (drc_index) {
         _FDT(fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index));
@@ -988,8 +1053,7 @@  static void *spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev,
         sprintf(nodename, "pci@%d", slot);
     }
     offset = fdt_add_subnode(fdt, 0, nodename);
-    ret = spapr_populate_pci_child_dt(dev, fdt, offset, phb->index, drc_index,
-                                      drc_name);
+    ret = spapr_populate_pci_child_dt(dev, fdt, offset, phb, drc_index);
     g_assert(!ret);
 
     *dt_offset = offset;
@@ -1502,7 +1566,7 @@  static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
 typedef struct sPAPRFDT {
     void *fdt;
     int node_off;
-    uint32_t index;
+    sPAPRPHBState *sphb;
 } sPAPRFDT;
 
 static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
@@ -1523,7 +1587,7 @@  static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
         sprintf(nodename, "pci@%d", slot);
     }
     offset = fdt_add_subnode(p->fdt, p->node_off, nodename);
-    ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->index, drc_index, NULL);
+    ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->sphb, drc_index);
     g_assert(!ret);
 
     if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=
@@ -1538,7 +1602,7 @@  static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
 
     s_fdt.fdt = p->fdt;
     s_fdt.node_off = offset;
-    s_fdt.index = p->index;
+    s_fdt.sphb = p->sphb;
     pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
                         spapr_populate_pci_devices_dt,
                         &s_fdt);
@@ -1680,7 +1744,7 @@  int spapr_populate_pci_dt(sPAPRPHBState *phb,
     /* Populate tree nodes with PCI devices attached */
     s_fdt.fdt = fdt;
     s_fdt.node_off = bus_off;
-    s_fdt.index = phb->index;
+    s_fdt.sphb = phb;
     pci_for_each_device(bus, pci_bus_num(bus),
                         spapr_populate_pci_devices_dt,
                         &s_fdt);