diff mbox

[v5,4/4] spapr_pci: populate ibm,loc-code

Message ID 1432023962-32406-5-git-send-email-nikunj@linux.vnet.ibm.com
State New
Headers show

Commit Message

Nikunj A Dadhania May 19, 2015, 8:26 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. In failure cases use:
   vfio_<name>:<phb-index>:<slot>.<fn>

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 | 81 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 69 insertions(+), 12 deletions(-)

Comments

Alexey Kardashevskiy May 24, 2015, 11:24 a.m. UTC | #1
On 05/19/2015 06:26 PM, Nikunj A Dadhania 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. In failure cases use:
>     vfio_<name>:<phb-index>:<slot>.<fn>
>
> 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 | 81 ++++++++++++++++++++++++++++++++++++++++++++++--------
>   1 file changed, 69 insertions(+), 12 deletions(-)
>
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 12f1b9c..dd77119 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -769,6 +769,61 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
>       return drck->get_index(drc);
>   }
>
> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
> +{
> +    char *path = NULL, *buf = NULL;
> +    char *host = NULL;

Why not put them all in one line (or split into 3 lines :) )?


> +
> +    /* Get the PCI VFIO host id */
> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
> +    if (!host) {
> +        goto err_out;
> +    }
> +
> +    /* Construct the path of the file that will give us the DT location */
> +    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
> +    g_free(host);
> +    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
> +        goto err_out;
> +    }
> +    g_free(path);
> +
> +    /* Construct and read from host device tree the loc-code */
> +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
> +    g_free(buf);
> +    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {

If path==NULL, you'll return bad buf.


> +        goto err_out;
> +    }
> +    return buf;
> +
> +err_out:
> +    g_free(path);
> +    return NULL;
> +}
> +
> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
> +{
> +    char *buf;
> +    char devtype[16] = "qemu";

I still like "const char *s = "qemu";" better.


> +
> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
> +        buf = spapr_phb_vfio_get_loc_code(sphb, pdev);
> +        if (buf) {
> +            return buf;
> +        }
> +        snprintf(devtype, 4, "vfio");

With "const", you could just do devtype = "vfio".

Also,
=====
char devtype[16] = { 0xaa,  0xaa, 0xaa, 0xaa, 0xaa };
snprintf(devtype, 4, "vfio");
printf("%x %x %x\n", devtype[2], devtype[3], devtype[4]);
====

produces on my laptop (gcc 4.9.2) this:

[aik@aik ~]$ ./a.out
69 0 ffffffaa


Is it different where you tested this?


> +    }
> +    /*
> +     * For emulated devices and VFIO-failure case, make up
> +     * the loc-code.
> +     */
> +    buf = g_strdup_printf("%s_%s:%02d:%02d.%1d",

How is "1d" different here from just "d"? If @devfn>10, all digits will be 
printed.


> +                          devtype, pdev->name,
> +                          sphb->index, PCI_SLOT(pdev->devfn),
> +                          PCI_FUNC(pdev->devfn));
> +    return buf;
> +}
> +
>   /* 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 */
> @@ -906,12 +961,12 @@ static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
>   }
>
>   static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
> -                                       sPAPRPHBState *sphb,
> -                                       const char *drc_name)
> +                                       sPAPRPHBState *sphb)
>   {
>       ResourceProps rp;
>       bool is_bridge = false;
>       int pci_status;
> +    char *buf = NULL;
>       uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
>
>       if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
> @@ -973,9 +1028,13 @@ 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_phb_get_loc_code(sphb, dev);
> +    if (!buf) {
> +        error_report("Failed setting the ibm,loc-code");
> +        return -1;
> +    } else {

No need in "else".


> +        _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));
> @@ -1003,8 +1062,7 @@ typedef struct sPAPRFDT {
>   } sPAPRFDT;
>
>   /* create OF node for pci device and required OF DT properties */
> -static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
> -                                     const char *drc_name)
> +static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p)
>   {
>       int offset, ret;
>       char nodename[64];
> @@ -1017,8 +1075,8 @@ static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
>           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->sphb,
> -                                      drc_name);
> +
> +    ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->sphb);
>       g_assert(!ret);
>       if (ret) {
>           return 0;
> @@ -1033,7 +1091,6 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>   {
>       sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>       DeviceState *dev = DEVICE(pdev);
> -    const char *drc_name = drck->get_name(drc);
>       int fdt_start_offset = 0, fdt_size;
>       sPAPRFDT s_fdt = {NULL, 0, NULL};
>
> @@ -1041,7 +1098,7 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>           s_fdt.fdt = create_device_tree(&fdt_size);
>           s_fdt.sphb = phb;
>           s_fdt.node_off = 0;
> -        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt, drc_name);
> +        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt);
>           if (!fdt_start_offset) {
>               error_setg(errp, "Failed to create pci child device tree node");
>               goto out;
> @@ -1519,7 +1576,7 @@ static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
>       int offset;
>       sPAPRFDT s_fdt;
>
> -    offset = spapr_create_pci_child_dt(pdev, p, NULL);
> +    offset = spapr_create_pci_child_dt(pdev, p);
>       if (!offset) {
>           error_report("Failed to create pci child device tree node");
>           return;
>
Nikunj A Dadhania May 25, 2015, 4:58 a.m. UTC | #2
Alexey Kardashevskiy <aik@ozlabs.ru> writes:

> On 05/19/2015 06:26 PM, Nikunj A Dadhania 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. In failure cases use:
>>     vfio_<name>:<phb-index>:<slot>.<fn>
>>
>> 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 | 81 ++++++++++++++++++++++++++++++++++++++++++++++--------
>>   1 file changed, 69 insertions(+), 12 deletions(-)
>>
>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>> index 12f1b9c..dd77119 100644
>> --- a/hw/ppc/spapr_pci.c
>> +++ b/hw/ppc/spapr_pci.c
>> @@ -769,6 +769,61 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
>>       return drck->get_index(drc);
>>   }
>>
>> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>> +{
>> +    char *path = NULL, *buf = NULL;
>> +    char *host = NULL;
>
> Why not put them all in one line (or split into 3 lines :) )?

Sure.

>
>
>> +
>> +    /* Get the PCI VFIO host id */
>> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
>> +    if (!host) {
>> +        goto err_out;
>> +    }
>> +
>> +    /* Construct the path of the file that will give us the DT location */
>> +    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
>> +    g_free(host);
>> +    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
>> +        goto err_out;
>> +    }
>> +    g_free(path);
>> +
>> +    /* Construct and read from host device tree the loc-code */
>> +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
>> +    g_free(buf);
>> +    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
>
> If path==NULL, you'll return bad buf.

Oh, got it wrong.

>
>
>> +        goto err_out;
>> +    }
>> +    return buf;
>> +
>> +err_out:
>> +    g_free(path);
>> +    return NULL;
>> +}
>> +
>> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
>> +{
>> +    char *buf;
>> +    char devtype[16] = "qemu";
>
> I still like "const char *s = "qemu";" better.

Yes, was waiting for respin after review.

>
>
>> +
>> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
>> +        buf = spapr_phb_vfio_get_loc_code(sphb, pdev);
>> +        if (buf) {
>> +            return buf;
>> +        }
>> +        snprintf(devtype, 4, "vfio");
>
> With "const", you could just do devtype = "vfio".
>
> Also,
> =====
> char devtype[16] = { 0xaa,  0xaa, 0xaa, 0xaa, 0xaa };
> snprintf(devtype, 4, "vfio");
> printf("%x %x %x\n", devtype[2], devtype[3], devtype[4]);
> ====
>
> produces on my laptop (gcc 4.9.2) this:
>
> [aik@aik ~]$ ./a.out
> 69 0 ffffffaa
>
>
> Is it different where you tested this?
>
>
>> +    }
>> +    /*
>> +     * For emulated devices and VFIO-failure case, make up
>> +     * the loc-code.
>> +     */
>> +    buf = g_strdup_printf("%s_%s:%02d:%02d.%1d",
>
> How is "1d" different here from just "d"? If @devfn>10, all digits will be 
> printed.

A device can have only 8 functions, right ?

>
>
>> +                          devtype, pdev->name,
>> +                          sphb->index, PCI_SLOT(pdev->devfn),
>> +                          PCI_FUNC(pdev->devfn));
>> +    return buf;
>> +}
>> +
>>   /* 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 */
>> @@ -906,12 +961,12 @@ static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
>>   }
>>
>>   static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
>> -                                       sPAPRPHBState *sphb,
>> -                                       const char *drc_name)
>> +                                       sPAPRPHBState *sphb)
>>   {
>>       ResourceProps rp;
>>       bool is_bridge = false;
>>       int pci_status;
>> +    char *buf = NULL;
>>       uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
>>
>>       if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
>> @@ -973,9 +1028,13 @@ 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_phb_get_loc_code(sphb, dev);
>> +    if (!buf) {
>> +        error_report("Failed setting the ibm,loc-code");
>> +        return -1;
>> +    } else {
>
> No need in "else".

Yeah.

>
>> +        _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));
>> @@ -1003,8 +1062,7 @@ typedef struct sPAPRFDT {
>>   } sPAPRFDT;
>>
>>   /* create OF node for pci device and required OF DT properties */
>> -static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
>> -                                     const char *drc_name)
>> +static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p)
>>   {
>>       int offset, ret;
>>       char nodename[64];
>> @@ -1017,8 +1075,8 @@ static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
>>           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->sphb,
>> -                                      drc_name);
>> +
>> +    ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->sphb);
>>       g_assert(!ret);
>>       if (ret) {
>>           return 0;
>> @@ -1033,7 +1091,6 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>>   {
>>       sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>>       DeviceState *dev = DEVICE(pdev);
>> -    const char *drc_name = drck->get_name(drc);
>>       int fdt_start_offset = 0, fdt_size;
>>       sPAPRFDT s_fdt = {NULL, 0, NULL};
>>
>> @@ -1041,7 +1098,7 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>>           s_fdt.fdt = create_device_tree(&fdt_size);
>>           s_fdt.sphb = phb;
>>           s_fdt.node_off = 0;
>> -        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt, drc_name);
>> +        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt);
>>           if (!fdt_start_offset) {
>>               error_setg(errp, "Failed to create pci child device tree node");
>>               goto out;
>> @@ -1519,7 +1576,7 @@ static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
>>       int offset;
>>       sPAPRFDT s_fdt;
>>
>> -    offset = spapr_create_pci_child_dt(pdev, p, NULL);
>> +    offset = spapr_create_pci_child_dt(pdev, p);
>>       if (!offset) {
>>           error_report("Failed to create pci child device tree node");
>>           return;
>>
>
>
> -- 
> Alexey
Alexey Kardashevskiy May 25, 2015, 10:06 a.m. UTC | #3
On 05/25/2015 02:58 PM, Nikunj A Dadhania wrote:
> Alexey Kardashevskiy <aik@ozlabs.ru> writes:
>
>> On 05/19/2015 06:26 PM, Nikunj A Dadhania 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. In failure cases use:
>>>      vfio_<name>:<phb-index>:<slot>.<fn>
>>>
>>> 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 | 81 ++++++++++++++++++++++++++++++++++++++++++++++--------
>>>    1 file changed, 69 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>>> index 12f1b9c..dd77119 100644
>>> --- a/hw/ppc/spapr_pci.c
>>> +++ b/hw/ppc/spapr_pci.c
>>> @@ -769,6 +769,61 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
>>>        return drck->get_index(drc);
>>>    }
>>>
>>> +static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
>>> +{
>>> +    char *path = NULL, *buf = NULL;
>>> +    char *host = NULL;
>>
>> Why not put them all in one line (or split into 3 lines :) )?
>
> Sure.
>
>>
>>
>>> +
>>> +    /* Get the PCI VFIO host id */
>>> +    host = object_property_get_str(OBJECT(pdev), "host", NULL);
>>> +    if (!host) {
>>> +        goto err_out;
>>> +    }
>>> +
>>> +    /* Construct the path of the file that will give us the DT location */
>>> +    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
>>> +    g_free(host);
>>> +    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
>>> +        goto err_out;
>>> +    }
>>> +    g_free(path);
>>> +
>>> +    /* Construct and read from host device tree the loc-code */
>>> +    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
>>> +    g_free(buf);
>>> +    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
>>
>> If path==NULL, you'll return bad buf.
>
> Oh, got it wrong.
>
>>
>>
>>> +        goto err_out;
>>> +    }
>>> +    return buf;
>>> +
>>> +err_out:
>>> +    g_free(path);
>>> +    return NULL;
>>> +}
>>> +
>>> +static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
>>> +{
>>> +    char *buf;
>>> +    char devtype[16] = "qemu";
>>
>> I still like "const char *s = "qemu";" better.
>
> Yes, was waiting for respin after review.
>
>>
>>
>>> +
>>> +    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
>>> +        buf = spapr_phb_vfio_get_loc_code(sphb, pdev);
>>> +        if (buf) {
>>> +            return buf;
>>> +        }
>>> +        snprintf(devtype, 4, "vfio");
>>
>> With "const", you could just do devtype = "vfio".
>>
>> Also,
>> =====
>> char devtype[16] = { 0xaa,  0xaa, 0xaa, 0xaa, 0xaa };
>> snprintf(devtype, 4, "vfio");
>> printf("%x %x %x\n", devtype[2], devtype[3], devtype[4]);
>> ====
>>
>> produces on my laptop (gcc 4.9.2) this:
>>
>> [aik@aik ~]$ ./a.out
>> 69 0 ffffffaa
>>
>>
>> Is it different where you tested this?
>>
>>
>>> +    }
>>> +    /*
>>> +     * For emulated devices and VFIO-failure case, make up
>>> +     * the loc-code.
>>> +     */
>>> +    buf = g_strdup_printf("%s_%s:%02d:%02d.%1d",
>>
>> How is "1d" different here from just "d"? If @devfn>10, all digits will be
>> printed.
>
> A device can have only 8 functions, right ?


Yes. It is "%d" (decimal) so "1" is a minimum field length anyway ("1" only 
makes sense for strings imho). And if a function number is bigger than 9, 
print() will print all digits, not just the last one. So %d==%1d but I 
would never grep for "%02d:%02d.%1d", I would grep for "%02d:%02d.%d".

[few minutes later] And I just did. And I found that most places actually 
use "%02x:%02x.%x" (trace-events, hw/pci/pci.c, hw/vfio/pci.c) and only one 
(get_pci_host_devaddr) uses "%d" for a function (and even there "%02x" is 
used for a bus and a slot, not "%02d").




>
>>
>>
>>> +                          devtype, pdev->name,
>>> +                          sphb->index, PCI_SLOT(pdev->devfn),
>>> +                          PCI_FUNC(pdev->devfn));
>>> +    return buf;
>>> +}
>>> +
>>>    /* 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 */
>>> @@ -906,12 +961,12 @@ static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
>>>    }
>>>
>>>    static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
>>> -                                       sPAPRPHBState *sphb,
>>> -                                       const char *drc_name)
>>> +                                       sPAPRPHBState *sphb)
>>>    {
>>>        ResourceProps rp;
>>>        bool is_bridge = false;
>>>        int pci_status;
>>> +    char *buf = NULL;
>>>        uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
>>>
>>>        if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
>>> @@ -973,9 +1028,13 @@ 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_phb_get_loc_code(sphb, dev);
>>> +    if (!buf) {
>>> +        error_report("Failed setting the ibm,loc-code");
>>> +        return -1;
>>> +    } else {
>>
>> No need in "else".
>
> Yeah.
>
>>
>>> +        _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));
>>> @@ -1003,8 +1062,7 @@ typedef struct sPAPRFDT {
>>>    } sPAPRFDT;
>>>
>>>    /* create OF node for pci device and required OF DT properties */
>>> -static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
>>> -                                     const char *drc_name)
>>> +static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p)
>>>    {
>>>        int offset, ret;
>>>        char nodename[64];
>>> @@ -1017,8 +1075,8 @@ static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
>>>            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->sphb,
>>> -                                      drc_name);
>>> +
>>> +    ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->sphb);
>>>        g_assert(!ret);
>>>        if (ret) {
>>>            return 0;
>>> @@ -1033,7 +1091,6 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>>>    {
>>>        sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>>>        DeviceState *dev = DEVICE(pdev);
>>> -    const char *drc_name = drck->get_name(drc);
>>>        int fdt_start_offset = 0, fdt_size;
>>>        sPAPRFDT s_fdt = {NULL, 0, NULL};
>>>
>>> @@ -1041,7 +1098,7 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
>>>            s_fdt.fdt = create_device_tree(&fdt_size);
>>>            s_fdt.sphb = phb;
>>>            s_fdt.node_off = 0;
>>> -        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt, drc_name);
>>> +        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt);
>>>            if (!fdt_start_offset) {
>>>                error_setg(errp, "Failed to create pci child device tree node");
>>>                goto out;
>>> @@ -1519,7 +1576,7 @@ static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
>>>        int offset;
>>>        sPAPRFDT s_fdt;
>>>
>>> -    offset = spapr_create_pci_child_dt(pdev, p, NULL);
>>> +    offset = spapr_create_pci_child_dt(pdev, p);
>>>        if (!offset) {
>>>            error_report("Failed to create pci child device tree node");
>>>            return;
>>>
>>
>>
>> --
>> Alexey
>
Nikunj A Dadhania May 25, 2015, 10:27 a.m. UTC | #4
Alexey Kardashevskiy <aik@ozlabs.ru> writes:

> On 05/25/2015 02:58 PM, Nikunj A Dadhania wrote:
>> Alexey Kardashevskiy <aik@ozlabs.ru> writes:
>>
>>>
>>>> +    }
>>>> +    /*
>>>> +     * For emulated devices and VFIO-failure case, make up
>>>> +     * the loc-code.
>>>> +     */
>>>> +    buf = g_strdup_printf("%s_%s:%02d:%02d.%1d",
>>>
>>> How is "1d" different here from just "d"? If @devfn>10, all digits will be
>>> printed.
>>
>> A device can have only 8 functions, right ?
>
>
> Yes. It is "%d" (decimal) so "1" is a minimum field length anyway ("1" only 
> makes sense for strings imho). And if a function number is bigger than 9, 
> print() will print all digits, not just the last one. So %d==%1d but I 
> would never grep for "%02d:%02d.%1d", I would grep for "%02d:%02d.%d".
>
> [few minutes later] And I just did. And I found that most places actually 
> use "%02x:%02x.%x" (trace-events, hw/pci/pci.c, hw/vfio/pci.c) and only one 
> (get_pci_host_devaddr) uses "%d" for a function (and even there "%02x" is 
> used for a bus and a slot, not "%02d").

Using "%02x:%02x.%x" should be fine then, I will change the code
accordingly.

Regards
Nikunj
diff mbox

Patch

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 12f1b9c..dd77119 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -769,6 +769,61 @@  static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
     return drck->get_index(drc);
 }
 
+static char *spapr_phb_vfio_get_loc_code(sPAPRPHBState *sphb,  PCIDevice *pdev)
+{
+    char *path = NULL, *buf = NULL;
+    char *host = NULL;
+
+    /* Get the PCI VFIO host id */
+    host = object_property_get_str(OBJECT(pdev), "host", NULL);
+    if (!host) {
+        goto err_out;
+    }
+
+    /* Construct the path of the file that will give us the DT location */
+    path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
+    g_free(host);
+    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
+        goto err_out;
+    }
+    g_free(path);
+
+    /* Construct and read from host device tree the loc-code */
+    path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
+    g_free(buf);
+    if (path && !g_file_get_contents(path, &buf, NULL, NULL)) {
+        goto err_out;
+    }
+    return buf;
+
+err_out:
+    g_free(path);
+    return NULL;
+}
+
+static char *spapr_phb_get_loc_code(sPAPRPHBState *sphb, PCIDevice *pdev)
+{
+    char *buf;
+    char devtype[16] = "qemu";
+
+    if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
+        buf = spapr_phb_vfio_get_loc_code(sphb, pdev);
+        if (buf) {
+            return buf;
+        }
+        snprintf(devtype, 4, "vfio");
+    }
+    /*
+     * For emulated devices and VFIO-failure case, make up
+     * the loc-code.
+     */
+    buf = g_strdup_printf("%s_%s:%02d:%02d.%1d",
+                          devtype, pdev->name,
+                          sphb->index, PCI_SLOT(pdev->devfn),
+                          PCI_FUNC(pdev->devfn));
+    return buf;
+}
+
 /* 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 */
@@ -906,12 +961,12 @@  static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
 }
 
 static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
-                                       sPAPRPHBState *sphb,
-                                       const char *drc_name)
+                                       sPAPRPHBState *sphb)
 {
     ResourceProps rp;
     bool is_bridge = false;
     int pci_status;
+    char *buf = NULL;
     uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
 
     if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
@@ -973,9 +1028,13 @@  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_phb_get_loc_code(sphb, dev);
+    if (!buf) {
+        error_report("Failed setting the ibm,loc-code");
+        return -1;
+    } else {
+        _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));
@@ -1003,8 +1062,7 @@  typedef struct sPAPRFDT {
 } sPAPRFDT;
 
 /* create OF node for pci device and required OF DT properties */
-static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
-                                     const char *drc_name)
+static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p)
 {
     int offset, ret;
     char nodename[64];
@@ -1017,8 +1075,8 @@  static int spapr_create_pci_child_dt(PCIDevice *pdev, sPAPRFDT *p,
         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->sphb,
-                                      drc_name);
+
+    ret = spapr_populate_pci_child_dt(pdev, p->fdt, offset, p->sphb);
     g_assert(!ret);
     if (ret) {
         return 0;
@@ -1033,7 +1091,6 @@  static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
 {
     sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
     DeviceState *dev = DEVICE(pdev);
-    const char *drc_name = drck->get_name(drc);
     int fdt_start_offset = 0, fdt_size;
     sPAPRFDT s_fdt = {NULL, 0, NULL};
 
@@ -1041,7 +1098,7 @@  static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
         s_fdt.fdt = create_device_tree(&fdt_size);
         s_fdt.sphb = phb;
         s_fdt.node_off = 0;
-        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt, drc_name);
+        fdt_start_offset = spapr_create_pci_child_dt(pdev, &s_fdt);
         if (!fdt_start_offset) {
             error_setg(errp, "Failed to create pci child device tree node");
             goto out;
@@ -1519,7 +1576,7 @@  static void spapr_populate_pci_devices_dt(PCIBus *bus, PCIDevice *pdev,
     int offset;
     sPAPRFDT s_fdt;
 
-    offset = spapr_create_pci_child_dt(pdev, p, NULL);
+    offset = spapr_create_pci_child_dt(pdev, p);
     if (!offset) {
         error_report("Failed to create pci child device tree node");
         return;