linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
To: Lizhi Hou <lizhi.hou@xilinx.com>
Cc: linux-pci@vger.kernel.org, devicetree@vger.kernel.org,
	robh@kernel.org, yilun.xu@intel.com, maxz@xilinx.com,
	sonal.santan@xilinx.com, yliu@xilinx.com,
	michal.simek@xilinx.com, stefanos@xilinx.com, trix@redhat.com,
	mdf@kernel.org, dwmw2@infradead.org,
	linux-kernel@vger.kernel.org, Max Zhen <max.zhen@xilinx.com>
Subject: Re: [PATCH V1 RESEND 1/4] pci: add interface to create pci-ep device tree node
Date: Tue, 21 Jun 2022 20:42:11 +0530	[thread overview]
Message-ID: <20220621151211.GB28880@thinkpad> (raw)
In-Reply-To: <20220305052304.726050-2-lizhi.hou@xilinx.com>

On Fri, Mar 04, 2022 at 09:23:01PM -0800, Lizhi Hou wrote:
> This patch enables PCIe device to uses flattened device tree to describe
> apertures in its PCIe BARs. The aperture address consists of PCIe BAR index
> and offset.
> 
> For this kind of device, the driver probe routine calls the new added
> interface to create a device tree node. This device tree node is attached
> under system device tree root. Then the driver may load the flatten device
> tree overlay and attach it under this node. And the node also contains
> 'ranges' property which is used to translate aperture address(BAR index
> and offset) to CPU address.
> 

This is the devicetree support for the PCI endpoint subsystem. Hence, the
code should live under drivers/pci/endpoint/.

But let's first settle on the structure of the devicetree binding first.

Thanks,
Mani

> Signed-off-by: Sonal Santan <sonal.santan@xilinx.com>
> Signed-off-by: Max Zhen <max.zhen@xilinx.com>
> Signed-off-by: Lizhi Hou <lizhi.hou@xilinx.com>
> ---
>  drivers/pci/of.c       | 180 +++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_pci.h |  15 ++++
>  2 files changed, 195 insertions(+)
> 
> diff --git a/drivers/pci/of.c b/drivers/pci/of.c
> index cb2e8351c2cc..198f08351070 100644
> --- a/drivers/pci/of.c
> +++ b/drivers/pci/of.c
> @@ -605,6 +605,186 @@ int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge)
>  	return pci_parse_request_of_pci_ranges(dev, bridge);
>  }
>  
> +#if IS_ENABLED(CONFIG_OF_DYNAMIC)
> +
> +static void devm_of_pci_destroy_bus_endpoint(struct device *dev, void *res)
> +{
> +	struct device_node *node = res;
> +
> +	of_detach_node(node);
> +}
> +
> +static int of_ep_add_property(struct device *dev, struct property **proplist, const char *name,
> +			      const int length, void *value)
> +{
> +	struct property *new;
> +
> +	new = devm_kzalloc(dev, sizeof(*new), GFP_KERNEL);
> +	if (!new)
> +		return -ENOMEM;
> +
> +	new->name = devm_kstrdup(dev, name, GFP_KERNEL);
> +	if (!new->name)
> +		return -ENOMEM;
> +
> +	new->value = devm_kmalloc(dev, length, GFP_KERNEL);
> +	if (!new->value)
> +		return -ENOMEM;
> +
> +	memcpy(new->value, value, length);
> +	new->length = length;
> +	new->next = *proplist;
> +	*proplist = new;
> +
> +	return 0;
> +}
> +
> +static struct device_node *of_ep_alloc_node(struct pci_dev *pdev, const char *name)
> +{
> +	struct device_node *node;
> +	char *full_name;
> +
> +	node = devres_alloc(devm_of_pci_destroy_bus_endpoint, sizeof(*node), GFP_KERNEL);
> +	if (!node)
> +		return NULL;
> +
> +	full_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "/%s@%llx", name,
> +				   (u64)pci_resource_start(pdev, 0));
> +	if (!full_name)
> +		return NULL;
> +
> +	node->parent = of_root;
> +	node->full_name = full_name;
> +	of_node_set_flag(node, OF_DYNAMIC);
> +	of_node_init(node);
> +
> +	return node;
> +}
> +
> +/**
> + * devm_of_pci_create_bus_endpoint - Create a device node for the given pci device.
> + * @pdev: PCI device pointer.
> + *
> + * For PCI device which uses flattened device tree to describe apertures in its BARs,
> + * a device node for the given pci device is required. Then the flattened device tree
> + * overlay from the device can be applied to the base tree.
> + * The device node is under root node and act like bus node. It contains a "ranges"
> + * property which is used for address translation of its children. Each child node
> + * corresponds an aperture and use BAR index and offset as its address.
> +
> + * Returns 0 on success or a negative error-code on failure.
> + */
> +int devm_of_pci_create_bus_endpoint(struct pci_dev *pdev)
> +{
> +	struct property *proplist = NULL;
> +	struct device *dev = &pdev->dev;
> +	int range_ncells, addr_ncells;
> +	struct device_node *node;
> +	void *prop = NULL;
> +	u32 *range_cell;
> +	__be32 val;
> +	int i, ret;
> +
> +	node = of_ep_alloc_node(pdev, "pci-ep-bus");
> +	if (!node)
> +		return -ENOMEM;
> +
> +	/* the endpoint node works as 'simple-bus' to translate aperture addresses. */
> +	prop = "simple-bus";
> +	ret = of_ep_add_property(dev, &proplist, "compatible", strlen(prop) + 1, prop);
> +	if (ret)
> +		goto cleanup;
> +
> +	/* The address and size cells of nodes underneath are 2 */
> +	val = cpu_to_be32(2);
> +	ret = of_ep_add_property(dev, &proplist, "#address-cells", sizeof(u32), &val);
> +	if (ret)
> +		goto cleanup;
> +
> +	ret = of_ep_add_property(dev, &proplist, "#size-cells", sizeof(u32), &val);
> +	if (ret)
> +		goto cleanup;
> +
> +	/* child address format: 0xIooooooo oooooooo, I = bar index, o = offset on bar */
> +	addr_ncells = of_n_addr_cells(node);
> +	if (addr_ncells > 2) {
> +		/* does not support number of address cells greater than 2 */
> +		ret = -EINVAL;
> +		goto cleanup;
> +	}
> +
> +	/* range cells include <node addr cells> <child addr cells> <child size cells> */
> +	range_ncells = addr_ncells + 4;
> +	prop = kzalloc(range_ncells * sizeof(u32) * PCI_STD_NUM_BARS, GFP_KERNEL);
> +	if (!prop) {
> +		ret = -ENOMEM;
> +		goto cleanup;
> +	}
> +
> +	range_cell = prop;
> +	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> +		if (!pci_resource_len(pdev, i))
> +			continue;
> +		/* highest 4 bits of address are bar index */
> +		*(__be64 *)range_cell = cpu_to_be64((u64)i << 60);
> +		range_cell += 2;
> +		if (addr_ncells == 2)
> +			*(__be64 *)range_cell = cpu_to_be64((u64)pci_resource_start(pdev, i));
> +		else
> +			*(__be32 *)range_cell = cpu_to_be32((u32)pci_resource_start(pdev, i));
> +
> +		range_cell += addr_ncells;
> +		*(__be64 *)range_cell = cpu_to_be64((u64)pci_resource_len(pdev, i));
> +		range_cell += 2;
> +	}
> +
> +	/* error out if there is not PCI BAR been found */
> +	if ((void *)range_cell == prop) {
> +		ret = -EINVAL;
> +		goto cleanup;
> +	}
> +
> +	ret = of_ep_add_property(dev, &proplist, "ranges", (void *)range_cell - prop, prop);
> +	kfree(prop);
> +	if (ret)
> +		goto cleanup;
> +
> +	node->properties = proplist;
> +	ret = of_attach_node(node);
> +	if (ret)
> +		goto cleanup;
> +
> +	devres_add(dev, node);
> +
> +	return 0;
> +
> +cleanup:
> +	kfree(prop);
> +	if (node)
> +		devres_free(node);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(devm_of_pci_create_bus_endpoint);
> +
> +struct device_node *of_pci_find_bus_endpoint(struct pci_dev *pdev)
> +{
> +	struct device_node *dn;
> +	char *path;
> +
> +	path = kasprintf(GFP_KERNEL, "/pci-ep-bus@%llx",
> +			 (u64)pci_resource_start(pdev, 0));
> +	if (!path)
> +		return NULL;
> +
> +	dn = of_find_node_by_path(path);
> +	kfree(path);
> +
> +	return dn;
> +}
> +EXPORT_SYMBOL_GPL(of_pci_find_bus_endpoint);
> +#endif /* CONFIG_OF_DYNAMIC */
> +
>  #endif /* CONFIG_PCI */
>  
>  /**
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> index 29658c0ee71f..c1d86be321b2 100644
> --- a/include/linux/of_pci.h
> +++ b/include/linux/of_pci.h
> @@ -38,4 +38,19 @@ of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
>  }
>  #endif
>  
> +#if IS_ENABLED(CONFIG_OF_DYNAMIC) && IS_ENABLED(CONFIG_PCI)
> +int devm_of_pci_create_bus_endpoint(struct pci_dev *pdev);
> +struct device_node *of_pci_find_bus_endpoint(struct pci_dev *pdev);
> +#else
> +static inline int devm_of_pci_create_bus_endpoint(struct pci_dev *pdev)
> +{
> +	return -EINVAL;
> +}
> +
> +static inline struct device_node *of_pci_find_bus_endpoint(struct pci_dev *pdev)
> +{
> +	return NULL;
> +}
> +#endif
> +
>  #endif
> -- 
> 2.27.0
> 

-- 
மணிவண்ணன் சதாசிவம்

  parent reply	other threads:[~2022-06-21 15:14 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-05  5:23 [PATCH V1 RESEND 0/4] Infrastructure to define apertures in a PCIe device with a flattened device tree Lizhi Hou
2022-03-05  5:23 ` [PATCH V1 RESEND 1/4] pci: add interface to create pci-ep device tree node Lizhi Hou
2022-03-10 10:02   ` Dan Carpenter
2022-03-10 19:34   ` Bjorn Helgaas
2022-06-21 15:12   ` Manivannan Sadhasivam [this message]
2022-03-05  5:23 ` [PATCH V1 RESEND 2/4] Documentation: devicetree: bindings: add binding for PCIe endpoint bus Lizhi Hou
2022-03-06 15:37   ` Tom Rix
2022-03-07 14:07     ` Rob Herring
2022-04-22 21:57       ` Lizhi Hou
2022-05-13 15:19         ` Lizhi Hou
2022-06-21 15:06   ` Manivannan Sadhasivam
2022-03-05  5:23 ` [PATCH V1 RESEND 3/4] fpga: xrt: management physical function driver Lizhi Hou
2022-06-21 15:16   ` Manivannan Sadhasivam
2023-06-30 16:38   ` Bjorn Helgaas
2022-03-05  5:23 ` [PATCH V1 RESEND 4/4] of: enhance overlay applying interface to specific target base node Lizhi Hou
2022-03-10 20:07   ` Rob Herring
2022-03-10 19:27 ` [PATCH V1 RESEND 0/4] Infrastructure to define apertures in a PCIe device with a flattened device tree Bjorn Helgaas

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=20220621151211.GB28880@thinkpad \
    --to=manivannan.sadhasivam@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dwmw2@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lizhi.hou@xilinx.com \
    --cc=max.zhen@xilinx.com \
    --cc=maxz@xilinx.com \
    --cc=mdf@kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=robh@kernel.org \
    --cc=sonal.santan@xilinx.com \
    --cc=stefanos@xilinx.com \
    --cc=trix@redhat.com \
    --cc=yilun.xu@intel.com \
    --cc=yliu@xilinx.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).