[U-Boot] [RFC PATCH 08/29] drivers: pci-uclass: add support for Single-Root I/O Virtualizaiton

Simon Glass sjg at chromium.org
Wed Nov 20 03:00:14 UTC 2019


Hi Suneel,

On Tue, 29 Oct 2019 at 14:08, Suneel Garapati <suneelglinux at gmail.com> wrote:
>
> From: Suneel Garapati <sgarapati at marvell.com>
>
> If SR-IOV capability is present, use it to initialize Virtual function
> (VF) PCI device instances. pci_sriov_init function will read SR-IOV
> registers to create VF devices under the PF PCI device and also bind
> driver if available. This function needs to be invoked from Physical
> function device driver which expects VF device support, creating
> minimal impact on existing framework.

Please expand your abbreviations .

This seems like a nice implementation overall, but it needs a sandbox
test and some documentation.

>
> Signed-off-by: Suneel Garapati <sgarapati at marvell.com>
> ---
>  drivers/pci/pci-uclass.c | 113 +++++++++++++++++++++++++++++++++++++++
>  include/pci.h            |  18 +++++++
>  2 files changed, 131 insertions(+)
>
> diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
> index 51f7135723..3be49c7115 100644
> --- a/drivers/pci/pci-uclass.c
> +++ b/drivers/pci/pci-uclass.c
> @@ -1535,6 +1535,119 @@ int dm_pci_flr(struct udevice *dev)
>         return 0;
>  }
>

is this supported to be exported? It needs a comment.

> +int pci_sriov_init(struct udevice *pdev, int vf_en)
> +{
> +       u16 vendor, device;
> +       struct udevice *bus;
> +       struct udevice *dev;
> +       pci_dev_t bdf;
> +       u16 ctrl;
> +       u16 num_vfs;
> +       u16 total_vf;
> +       u16 vf_offset;
> +       u16 vf_stride;
> +       int vf, ret;
> +       int pos;
> +
> +       pos = dm_pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
> +       if (!pos) {
> +               printf("Error: SRIOV capability not found\n");

debug()

> +               return -ENOENT;
> +       }
> +
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_CTRL, &ctrl);
> +
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_TOTAL_VF, &total_vf);
> +       if (vf_en > total_vf)
> +               vf_en = total_vf;
> +       dm_pci_write_config16(pdev, pos + PCI_SRIOV_NUM_VF, vf_en);
> +
> +       ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
> +       dm_pci_write_config16(pdev, pos + PCI_SRIOV_CTRL, ctrl);
> +
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_NUM_VF, &num_vfs);
> +       if (num_vfs > vf_en)
> +               num_vfs = vf_en;
> +
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_VF_OFFSET, &vf_offset);
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_VF_STRIDE, &vf_stride);
> +
> +       dm_pci_read_config16(pdev, PCI_VENDOR_ID, &vendor);
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_VF_DID, &device);
> +
> +       bdf = dm_pci_get_bdf(pdev);
> +
> +       pci_get_bus(PCI_BUS(bdf), &bus);
> +
> +       if (!bus)
> +               return -ENODEV;
> +
> +       bdf += PCI_BDF(0, 0, vf_offset);
> +
> +       for (vf = 0; vf < num_vfs; vf++) {

This function is way too long - can you please split?

> +               struct pci_child_platdata *pplat;
> +               ulong class;
> +
> +               pci_bus_read_config(bus, bdf, PCI_CLASS_DEVICE,
> +                                   &class, PCI_SIZE_16);
> +
> +               debug("%s: bus %d/%s: found VF %x:%x\n", __func__,
> +                     bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
> +
> +               /* Find this device in the device tree */
> +               ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
> +
> +               if (ret == -ENODEV) {
> +                       struct pci_device_id find_id;
> +
> +                       memset(&find_id, 0, sizeof(find_id));

'\0'

> +
> +                       find_id.vendor = vendor;
> +                       find_id.device = device;
> +                       find_id.class = class;
> +
> +                       ret = pci_find_and_bind_driver(bus, &find_id,
> +                                                      bdf, &dev);

Can you share any code with pci_bind_bus_devices(), perhaps but
pulling part of it into a function?

> +
> +                       if (ret)
> +                               return ret;
> +               }
> +
> +               /* Update the platform data */
> +               pplat = dev_get_parent_platdata(dev);
> +               pplat->devfn = PCI_MASK_BUS(bdf);
> +               pplat->vendor = vendor;
> +               pplat->device = device;
> +               pplat->class = class;
> +               pplat->is_virtfn = true;
> +               pplat->pfdev = pdev;
> +               pplat->virtid = vf * vf_stride + vf_offset;
> +
> +               debug("%s: bus %d/%s: found VF %x:%x %x:%x class %lx id %x\n",
> +                     __func__, dev->seq, dev->name, PCI_DEV(bdf),
> +                     PCI_FUNC(bdf), vendor, device, class, pplat->virtid);
> +               bdf += PCI_BDF(0, 0, vf_stride);
> +       }
> +
> +       return 0;
> +}
> +
> +int pci_sriov_get_totalvfs(struct udevice *pdev)
> +{
> +       u16 total_vf;
> +       int pos;
> +
> +       pos = dm_pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
> +       if (!pos) {
> +               printf("Error: SRIOV capability not found\n");

debug()

> +               return -ENOENT;
> +       }
> +
> +       dm_pci_read_config16(pdev, pos + PCI_SRIOV_TOTAL_VF, &total_vf);
> +
> +       return total_vf;
> +}
> +
>  UCLASS_DRIVER(pci) = {
>         .id             = UCLASS_PCI,
>         .name           = "pci",
> diff --git a/include/pci.h b/include/pci.h
> index 0b14842285..1343d0e9fb 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -475,6 +475,17 @@
>  #define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
>  #define PCI_EXP_DEVCTL         8       /* Device Control */
>  #define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
> +/* Single Root I/O Virtualization Registers */
> +#define PCI_SRIOV_CAP          0x04    /* SR-IOV Capabilities */
> +#define PCI_SRIOV_CTRL         0x08    /* SR-IOV Control */
> +#define  PCI_SRIOV_CTRL_VFE    0x01    /* VF Enable */
> +#define  PCI_SRIOV_CTRL_MSE    0x08    /* VF Memory Space Enable */
> +#define PCI_SRIOV_INITIAL_VF   0x0c    /* Initial VFs */
> +#define PCI_SRIOV_TOTAL_VF     0x0e    /* Total VFs */
> +#define PCI_SRIOV_NUM_VF       0x10    /* Number of VFs */
> +#define PCI_SRIOV_VF_OFFSET    0x14    /* First VF Offset */
> +#define PCI_SRIOV_VF_STRIDE    0x16    /* Following VF Stride */
> +#define PCI_SRIOV_VF_DID       0x1a    /* VF Device ID */
>
>  /* Include the ID list */
>
> @@ -868,6 +879,10 @@ struct pci_child_platdata {
>         unsigned short vendor;
>         unsigned short device;
>         unsigned int class;
> +
> +       bool is_virtfn;
> +       struct udevice *pfdev;
> +       int virtid;

Add comments. You can see them above!

>  };
>
>  /* PCI bus operations */
> @@ -1178,6 +1193,9 @@ int pci_generic_mmap_read_config(
>         ulong *valuep,
>         enum pci_size_t size);
>
> +int pci_sriov_init(struct udevice *pdev, int vf_en);
> +int pci_sriov_get_totalvfs(struct udevice *pdev);

Comments!

> +
>  #ifdef CONFIG_DM_PCI_COMPAT
>  /* Compatibility with old naming */
>  static inline int pci_write_config_dword(pci_dev_t pcidev, int offset,
> --
> 2.23.0
>

Regards,
Simon


More information about the U-Boot mailing list