From: Alexey Kardashevskiy <aik@ozlabs.ru>
To: "Bryant G. Ly" <bryantly@linux.vnet.ibm.com>,
benh@kernel.crashing.org, paulus@samba.org, mpe@ellerman.id.au
Cc: seroyer@linux.vnet.ibm.com, jjalvare@linux.vnet.ibm.com,
alex.williamson@redhat.com, helgaas@kernel.org,
ruscur@russell.cc, linux-pci@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org, bodong@mellanox.com,
eli@mellanox.com, saeedm@mellanox.com
Subject: Re: [PATCH v1 7/7] pseries/setup: Add Initialization of VF Bars
Date: Mon, 18 Dec 2017 18:21:04 +1100 [thread overview]
Message-ID: <4ea33f2e-d98c-85ef-eedf-2e8ca49aa839@ozlabs.ru> (raw)
In-Reply-To: <20171213153242.98015-8-bryantly@linux.vnet.ibm.com>
On 14/12/17 02:32, Bryant G. Ly wrote:
> When enabling SR-IOV in pseries platform,
> the VF bar properties for a PF are reported on
> the device node in the device tree.
>
> This patch adds the IOV Bar resources to Linux
> structures from the device tree for later use
> when configuring SR-IOV by PF driver.
>
> Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
> Signed-off-by: Juan J. Alvarez <jjalvare@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/pci.h | 2 +
> arch/powerpc/kernel/pci_of_scan.c | 2 +-
> arch/powerpc/platforms/pseries/setup.c | 183 +++++++++++++++++++++++++++++++++
> 3 files changed, 186 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
> index 8dc32eacc97c..d82802ff5088 100644
> --- a/arch/powerpc/include/asm/pci.h
> +++ b/arch/powerpc/include/asm/pci.h
> @@ -121,6 +121,8 @@ extern int remove_phb_dynamic(struct pci_controller *phb);
> extern struct pci_dev *of_create_pci_dev(struct device_node *node,
> struct pci_bus *bus, int devfn);
>
> +extern unsigned int pci_parse_of_flags(u32 addr0, int bridge);
> +
> extern void of_scan_pci_bridge(struct pci_dev *dev);
>
> extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
> diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
> index 0d790f8432d2..20ceec4a5f5e 100644
> --- a/arch/powerpc/kernel/pci_of_scan.c
> +++ b/arch/powerpc/kernel/pci_of_scan.c
> @@ -38,7 +38,7 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
> * @addr0: value of 1st cell of a device tree PCI address.
> * @bridge: Set this flag if the address is from a bridge 'ranges' property
> */
> -static unsigned int pci_parse_of_flags(u32 addr0, int bridge)
> +unsigned int pci_parse_of_flags(u32 addr0, int bridge)
> {
> unsigned int flags = 0;
>
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index 5f1beb8367ac..ce28882cbde8 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -459,6 +459,181 @@ static void __init find_and_init_phbs(void)
> of_pci_check_probe_only();
> }
>
> +#ifdef CONFIG_PCI_IOV
> +enum rtas_iov_fw_value_map {
> + NUM_RES_PROPERTY = 0, ///< Number of Resources
> + LOW_INT = 1, ///< Lowest 32 bits of Address
> + START_OF_ENTRIES = 2, ///< Always start of entry
> + APERTURE_PROPERTY = 2, ///< Start of entry+ to Aperture Size
> + WDW_SIZE_PROPERTY = 4, ///< Start of entry+ to Window Size
> + NEXT_ENTRY = 7 ///< Go to next entry on array
> +};
> +
> +enum get_iov_fw_value_index {
> + BAR_ADDRS = 1, ///< Get Bar Address
> + APERTURE_SIZE = 2, ///< Get Aperture Size
> + WDW_SIZE = 3 ///< Get Window Size
> +};
> +
> +resource_size_t pseries_get_iov_fw_values(struct pci_dev *dev, int resno,
s/pseries_get_iov_fw_values/pseries_get_iov_fw_value/ as it returns a
single value.
> + enum get_iov_fw_value_index value)
> +{
> + struct vf_bar_wdw {
> + __be64 addr;
> + __be64 aperture_size;
> + __be64 wdw_size;
> + };
> +
> + struct vf_bar_wdw window_avail[PCI_SRIOV_NUM_BARS];
> + const int *indexes;
> + struct device_node *dn = pci_device_to_OF_node(dev);
> + int i, r, num_res;
> + resource_size_t return_value;
resource_size_t return_value = 0;
and remove initialization below. Also, way too long, @ret is a more common
name.
> +
> + indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
> + if (!indexes)
> + return 0;
> +
> + memset(window_avail,
> + 0, sizeof(struct vf_bar_wdw) * PCI_SRIOV_NUM_BARS);
This is more common way of doing the same initialization:
struct vf_bar_wdw {
__be64 addr;
__be64 aperture_size;
__be64 wdw_size;
} window_avail[PCI_SRIOV_NUM_BARS] = { 0 };
> + return_value = 0;
> + /*
> + * First element in the array is the number of Bars
> + * returned. Search through the list to find the matching
> + * bar
> + */
> + num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1);
if (resno >= num_res)
return 0; /* or an errror */
i = START_OF_ENTRIES + NEXT_ENTRY * resno;
switch (value) {
case BAR_ADDRS:
ret = f_read_number(&indexes[i], 2);
break;
case APERTURE_SIZE:
ret = of_read_number(&indexes[i + APERTURE_PROPERTY], 2);
break;
case WDW_SIZE:
ret = of_read_number(&indexes[i + WDW_SIZE_PROPERTY], 2);
break;
}
return ret;
}
and remove the reminder of the function, and window_avail, and vf_bar_wdw?
> + for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS;
> + i += NEXT_ENTRY, r++) {
> + window_avail[r].addr = of_read_number(&indexes[i], 2);
> + window_avail[r].aperture_size =
> + of_read_number(&indexes[i + APERTURE_PROPERTY], 2);
> + window_avail[r].wdw_size =
> + of_read_number(&indexes[i + WDW_SIZE_PROPERTY], 2);
> + }
> +
> + switch (value) {
> + case BAR_ADDRS:
> + return_value = window_avail[resno].addr;
> + break;
> + case APERTURE_SIZE:
> + return_value = window_avail[resno].aperture_size;
> + break;
> + case WDW_SIZE:
> + return_value = window_avail[resno].wdw_size;
> + break;
> + default:
> + break;
> + }
> + return return_value;
> +}
> +
> +void of_pci_parse_vf_bar_size(struct pci_dev *dev, const int *indexes)
It does not seem to make a lot of sense as a separate function imho...
> +{
> + struct resource *res;
> + resource_size_t base, size;
> + int i, r, num_res;
> +
> + num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1);
num_res = min_t(int, num_res, PCI_SRIOV_NUM_BARS) ? Matter of personal
taste though.
> + for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS;
> + i += NEXT_ENTRY, r++) {
> + res = &dev->resource[r + PCI_IOV_RESOURCES];
> + base = of_read_number(&indexes[i], 2);
> + size = of_read_number(&indexes[i + APERTURE_PROPERTY], 2);
> + res->flags = pci_parse_of_flags(of_read_number
> + (&indexes[i + LOW_INT], 1), 0);
> + res->flags |= (IORESOURCE_MEM_64 | IORESOURCE_PCI_FIXED);
> + res->name = pci_name(dev);
> + res->start = base;
> + res->end = base + size - 1;
The function name suggests it only parses sizes but just above it assigns
all resource parameters - size, address, flags.
> + }
> +}
> +
> +void of_pci_parse_iov_addrs(struct pci_dev *dev, const int *indexes)
> +{
> + struct resource *res, *root, *conflict;
> + resource_size_t base, size;
> + int i, r, num_res;
> +
> + /*
> + * First element in the array is the number of Bars
> + * returned. Search through the list to find the matching
> + * bars assign them from firmware into resources structure.
> + */
> + num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1);
> + for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS;
> + i += NEXT_ENTRY, r++) {
> + res = &dev->resource[r + PCI_IOV_RESOURCES];
> + base = of_read_number(&indexes[i], 2);
> + size = of_read_number(&indexes[i + WDW_SIZE_PROPERTY], 2);
> + res->name = pci_name(dev);
> + res->start = base;
> + res->end = base + size - 1;
> + root = pci_find_parent_resource(dev, res);
> +
> + if (!root)
> + root = &iomem_resource;
@dev here is a VF, right? I am not familiar with powervn much but from what
I see - the devices are sitting on a root bus of their own PHB and they all
either have a root returned from pci_find_parent_resource() or none of them
has a root and will fall back to &iomem_resource, or both cases are possible?
> + dev_dbg(&dev->dev,
> + "Pseries IOV BAR %d: trying firmware assignment %pR\n",
s/Pseries/pSeries/ ?
> + r + PCI_IOV_RESOURCES, res);
> + conflict = request_resource_conflict(root, res);
> + if (conflict) {
> + dev_info(&dev->dev,
> + "BAR %d: %pR conflicts with %s %pR\n",
> + r + PCI_IOV_RESOURCES, res,
> + conflict->name, conflict);
> + res->flags |= IORESOURCE_UNSET;
> + }
> + }
> +}
> +
> +static void pseries_pci_fixup_resources(struct pci_dev *pdev)
> +{
> + const int *indexes;
> + struct device_node *dn = pci_device_to_OF_node(pdev);
> +
> + /*Firmware must support open sriov otherwise dont configure*/
> + indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
> + if (!indexes)
> + return;
> + /* Assign the addresses from device tree*/
> + of_pci_parse_vf_bar_size(pdev, indexes);
> +}
> +
> +static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev)
> +{
> + const int *indexes;
> + struct device_node *dn = pci_device_to_OF_node(pdev);
> +
> + if (!pdev->is_physfn || pdev->is_added)
> + return;
> + /*Firmware must support open sriov otherwise dont configure*/
> + indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);
> + if (!indexes)
> + return;
> + /* Assign the addresses from device tree*/
> + of_pci_parse_iov_addrs(pdev, indexes);
> +}
> +
> +static resource_size_t pseries_pci_iov_resource_alignment(struct pci_dev *pdev,
> + int resno)
> +{
> + const __be32 *reg;
> + struct device_node *dn = pci_device_to_OF_node(pdev);
> +
> + /*Firmware must support open sriov otherwise report regular alignment*/
> + reg = of_get_property(dn, "ibm,is-open-sriov-pf", NULL);
> + if (!reg)
> + return pci_iov_resource_size(pdev, resno);
> +
> + if (!pdev->is_physfn)
> + return 0;
> + return pseries_get_iov_fw_values(pdev,
> + resno - PCI_IOV_RESOURCES,
> + APERTURE_SIZE);
> +}
> +#endif
> +
> static void __init pSeries_setup_arch(void)
> {
> set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
> @@ -490,6 +665,14 @@ static void __init pSeries_setup_arch(void)
> vpa_init(boot_cpuid);
> ppc_md.power_save = pseries_lpar_idle;
> ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
> +#ifdef CONFIG_PCI_IOV
> + ppc_md.pcibios_fixup_resources =
> + pseries_pci_fixup_resources;
> + ppc_md.pcibios_fixup_sriov =
> + pseries_pci_fixup_iov_resources;
> + ppc_md.pcibios_iov_resource_alignment =
> + pseries_pci_iov_resource_alignment;
> +#endif
I wish one day this horrible ppc_md monster dies and all these helpers will
go to PHB ops, hose ops, bus ops, whatever ops...
> } else {
> /* No special idle routine */
> ppc_md.enable_pmcs = power4_enable_pmcs;
>
--
Alexey
next prev parent reply other threads:[~2017-12-18 7:21 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-13 15:32 [PATCH v1 0/7] SR-IOV Enablement on PowerVM Bryant G. Ly
2017-12-13 15:32 ` [PATCH v1 1/7] platform/pseries: Update VF config space after EEH Bryant G. Ly
2017-12-18 3:48 ` Alexey Kardashevskiy
2017-12-13 15:32 ` [PATCH v1 2/7] powerpc/kernel: Add uevents in EEH error/resume Bryant G. Ly
2017-12-18 3:54 ` Alexey Kardashevskiy
2017-12-18 18:45 ` Bryant G. Ly
2017-12-18 4:15 ` Russell Currey
2017-12-13 15:32 ` [PATCH v1 3/7] platforms/pseries: Set eeh_pe of EEH_PE_VF type Bryant G. Ly
2017-12-18 4:31 ` Russell Currey
2017-12-18 4:34 ` Alexey Kardashevskiy
2017-12-18 19:29 ` Juan Alvarez
2017-12-13 15:32 ` [PATCH v1 4/7] powerpc/kernel Add EEH operations to notify resume Bryant G. Ly
2017-12-18 4:29 ` Russell Currey
2017-12-18 5:02 ` Alexey Kardashevskiy
2017-12-18 19:29 ` Juan Alvarez
2017-12-13 15:32 ` [PATCH v1 5/7] powerpc/kernel: Add EEH notify resume sysfs Bryant G. Ly
2017-12-13 15:32 ` [PATCH v1 6/7] pseries/pci: Associate PEs to VFs in configure SR-IOV Bryant G. Ly
2017-12-18 6:16 ` Alexey Kardashevskiy
2017-12-13 15:32 ` [PATCH v1 7/7] pseries/setup: Add Initialization of VF Bars Bryant G. Ly
2017-12-18 7:21 ` Alexey Kardashevskiy [this message]
2017-12-18 19:29 ` Juan Alvarez
2017-12-19 6:38 ` Alexey Kardashevskiy
2017-12-21 3:04 ` Juan Alvarez
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=4ea33f2e-d98c-85ef-eedf-2e8ca49aa839@ozlabs.ru \
--to=aik@ozlabs.ru \
--cc=alex.williamson@redhat.com \
--cc=benh@kernel.crashing.org \
--cc=bodong@mellanox.com \
--cc=bryantly@linux.vnet.ibm.com \
--cc=eli@mellanox.com \
--cc=helgaas@kernel.org \
--cc=jjalvare@linux.vnet.ibm.com \
--cc=linux-pci@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=mpe@ellerman.id.au \
--cc=paulus@samba.org \
--cc=ruscur@russell.cc \
--cc=saeedm@mellanox.com \
--cc=seroyer@linux.vnet.ibm.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).