diff mbox series

[v6,3/3] PCI: iproc: Add sorted dma ranges resource entries to host bridge

Message ID 1556892334-16270-4-git-send-email-srinath.mannam@broadcom.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show
Series PCIe Host request to reserve IOVA | expand

Commit Message

Srinath Mannam May 3, 2019, 2:05 p.m. UTC
The IPROC host controller allows only a subset of physical address space
as target of inbound PCI memory transactions addresses.

PCIe devices memory transactions targeting memory regions that
are not allowed for inbound transactions in the host controller
are rejected by the host controller and cannot reach the upstream
buses.

Firmware device tree description defines the DMA ranges that are
addressable by devices DMA transactions; parse the device tree
dma-ranges property and add its ranges to the PCI host bridge dma_ranges
list; the iova_reserve_pci_windows() call in the driver will reserve the
IOVA address ranges that are not addressable (ie memory holes in the
dma-ranges set) so that they are not allocated to PCI devices for DMA
transfers.

All allowed address ranges are listed in dma-ranges DT parameter.

Example:

dma-ranges = < \
  0x43000000 0x00 0x80000000 0x00 0x80000000 0x00 0x80000000 \
  0x43000000 0x08 0x00000000 0x08 0x00000000 0x08 0x00000000 \
  0x43000000 0x80 0x00000000 0x80 0x00000000 0x40 0x00000000>

In the above example of dma-ranges, memory address from

0x0 - 0x80000000,
0x100000000 - 0x800000000,
0x1000000000 - 0x8000000000 and
0x10000000000 - 0xffffffffffffffff.

are not allowed to be used as inbound addresses.

Based-on-patch-by: Oza Pawandeep <oza.oza@broadcom.com>
Signed-off-by: Srinath Mannam <srinath.mannam@broadcom.com>
[lorenzo.pieralisi@arm.com: updated commit log]
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
---
 drivers/pci/controller/pcie-iproc.c | 44 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

Comments

Bjorn Helgaas May 6, 2019, 9:12 p.m. UTC | #1
On Fri, May 03, 2019 at 07:35:34PM +0530, Srinath Mannam wrote:
> The IPROC host controller allows only a subset of physical address space
> as target of inbound PCI memory transactions addresses.
> 
> PCIe devices memory transactions targeting memory regions that
> are not allowed for inbound transactions in the host controller
> are rejected by the host controller and cannot reach the upstream
> buses.
> 
> Firmware device tree description defines the DMA ranges that are
> addressable by devices DMA transactions; parse the device tree
> dma-ranges property and add its ranges to the PCI host bridge dma_ranges
> list; the iova_reserve_pci_windows() call in the driver will reserve the
> IOVA address ranges that are not addressable (ie memory holes in the
> dma-ranges set) so that they are not allocated to PCI devices for DMA
> transfers.
> 
> All allowed address ranges are listed in dma-ranges DT parameter.
> 
> Example:
> 
> dma-ranges = < \
>   0x43000000 0x00 0x80000000 0x00 0x80000000 0x00 0x80000000 \
>   0x43000000 0x08 0x00000000 0x08 0x00000000 0x08 0x00000000 \
>   0x43000000 0x80 0x00000000 0x80 0x00000000 0x40 0x00000000>
> 
> In the above example of dma-ranges, memory address from
> 
> 0x0 - 0x80000000,
> 0x100000000 - 0x800000000,
> 0x1000000000 - 0x8000000000 and
> 0x10000000000 - 0xffffffffffffffff.
> 
> are not allowed to be used as inbound addresses.
> 
> Based-on-patch-by: Oza Pawandeep <oza.oza@broadcom.com>
> Signed-off-by: Srinath Mannam <srinath.mannam@broadcom.com>
> [lorenzo.pieralisi@arm.com: updated commit log]
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> ---
>  drivers/pci/controller/pcie-iproc.c | 44 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
> index c20fd6b..94ba5c0 100644
> --- a/drivers/pci/controller/pcie-iproc.c
> +++ b/drivers/pci/controller/pcie-iproc.c
> @@ -1146,11 +1146,43 @@ static int iproc_pcie_setup_ib(struct iproc_pcie *pcie,
>  	return ret;
>  }
>  
> +static int
> +iproc_pcie_add_dma_range(struct device *dev, struct list_head *resources,
> +			 struct of_pci_range *range)

Just FYI, I cherry-picked these commits from Lorenzo's branch to fix
the formatting of this prototype to match the rest of the file, e.g.:

>  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
> ...
>  static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
Lorenzo Pieralisi May 7, 2019, 9:41 a.m. UTC | #2
On Mon, May 06, 2019 at 04:12:08PM -0500, Bjorn Helgaas wrote:
> On Fri, May 03, 2019 at 07:35:34PM +0530, Srinath Mannam wrote:
> > The IPROC host controller allows only a subset of physical address space
> > as target of inbound PCI memory transactions addresses.
> > 
> > PCIe devices memory transactions targeting memory regions that
> > are not allowed for inbound transactions in the host controller
> > are rejected by the host controller and cannot reach the upstream
> > buses.
> > 
> > Firmware device tree description defines the DMA ranges that are
> > addressable by devices DMA transactions; parse the device tree
> > dma-ranges property and add its ranges to the PCI host bridge dma_ranges
> > list; the iova_reserve_pci_windows() call in the driver will reserve the
> > IOVA address ranges that are not addressable (ie memory holes in the
> > dma-ranges set) so that they are not allocated to PCI devices for DMA
> > transfers.
> > 
> > All allowed address ranges are listed in dma-ranges DT parameter.
> > 
> > Example:
> > 
> > dma-ranges = < \
> >   0x43000000 0x00 0x80000000 0x00 0x80000000 0x00 0x80000000 \
> >   0x43000000 0x08 0x00000000 0x08 0x00000000 0x08 0x00000000 \
> >   0x43000000 0x80 0x00000000 0x80 0x00000000 0x40 0x00000000>
> > 
> > In the above example of dma-ranges, memory address from
> > 
> > 0x0 - 0x80000000,
> > 0x100000000 - 0x800000000,
> > 0x1000000000 - 0x8000000000 and
> > 0x10000000000 - 0xffffffffffffffff.
> > 
> > are not allowed to be used as inbound addresses.
> > 
> > Based-on-patch-by: Oza Pawandeep <oza.oza@broadcom.com>
> > Signed-off-by: Srinath Mannam <srinath.mannam@broadcom.com>
> > [lorenzo.pieralisi@arm.com: updated commit log]
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
> > Reviewed-by: Eric Auger <eric.auger@redhat.com>
> > ---
> >  drivers/pci/controller/pcie-iproc.c | 44 ++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 43 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
> > index c20fd6b..94ba5c0 100644
> > --- a/drivers/pci/controller/pcie-iproc.c
> > +++ b/drivers/pci/controller/pcie-iproc.c
> > @@ -1146,11 +1146,43 @@ static int iproc_pcie_setup_ib(struct iproc_pcie *pcie,
> >  	return ret;
> >  }
> >  
> > +static int
> > +iproc_pcie_add_dma_range(struct device *dev, struct list_head *resources,
> > +			 struct of_pci_range *range)
> 
> Just FYI, I cherry-picked these commits from Lorenzo's branch to fix
> the formatting of this prototype to match the rest of the file, e.g.:

Thank you, I noticed too but I forgot to update it before merging
v6 from the list.

Thanks,
Lorenzo

> >  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
> > ...
> >  static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
Srinath Mannam May 7, 2019, 9:55 a.m. UTC | #3
Hi Bjorn,

Thank you.

Regards,
Srinath.

On Tue, May 7, 2019 at 3:11 PM Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
>
> On Mon, May 06, 2019 at 04:12:08PM -0500, Bjorn Helgaas wrote:
> > On Fri, May 03, 2019 at 07:35:34PM +0530, Srinath Mannam wrote:
> > > The IPROC host controller allows only a subset of physical address space
> > > as target of inbound PCI memory transactions addresses.
> > >
> > > PCIe devices memory transactions targeting memory regions that
> > > are not allowed for inbound transactions in the host controller
> > > are rejected by the host controller and cannot reach the upstream
> > > buses.
> > >
> > > Firmware device tree description defines the DMA ranges that are
> > > addressable by devices DMA transactions; parse the device tree
> > > dma-ranges property and add its ranges to the PCI host bridge dma_ranges
> > > list; the iova_reserve_pci_windows() call in the driver will reserve the
> > > IOVA address ranges that are not addressable (ie memory holes in the
> > > dma-ranges set) so that they are not allocated to PCI devices for DMA
> > > transfers.
> > >
> > > All allowed address ranges are listed in dma-ranges DT parameter.
> > >
> > > Example:
> > >
> > > dma-ranges = < \
> > >   0x43000000 0x00 0x80000000 0x00 0x80000000 0x00 0x80000000 \
> > >   0x43000000 0x08 0x00000000 0x08 0x00000000 0x08 0x00000000 \
> > >   0x43000000 0x80 0x00000000 0x80 0x00000000 0x40 0x00000000>
> > >
> > > In the above example of dma-ranges, memory address from
> > >
> > > 0x0 - 0x80000000,
> > > 0x100000000 - 0x800000000,
> > > 0x1000000000 - 0x8000000000 and
> > > 0x10000000000 - 0xffffffffffffffff.
> > >
> > > are not allowed to be used as inbound addresses.
> > >
> > > Based-on-patch-by: Oza Pawandeep <oza.oza@broadcom.com>
> > > Signed-off-by: Srinath Mannam <srinath.mannam@broadcom.com>
> > > [lorenzo.pieralisi@arm.com: updated commit log]
> > > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > > Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
> > > Reviewed-by: Eric Auger <eric.auger@redhat.com>
> > > ---
> > >  drivers/pci/controller/pcie-iproc.c | 44 ++++++++++++++++++++++++++++++++++++-
> > >  1 file changed, 43 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
> > > index c20fd6b..94ba5c0 100644
> > > --- a/drivers/pci/controller/pcie-iproc.c
> > > +++ b/drivers/pci/controller/pcie-iproc.c
> > > @@ -1146,11 +1146,43 @@ static int iproc_pcie_setup_ib(struct iproc_pcie *pcie,
> > >     return ret;
> > >  }
> > >
> > > +static int
> > > +iproc_pcie_add_dma_range(struct device *dev, struct list_head *resources,
> > > +                    struct of_pci_range *range)
> >
> > Just FYI, I cherry-picked these commits from Lorenzo's branch to fix
> > the formatting of this prototype to match the rest of the file, e.g.:
>
> Thank you, I noticed too but I forgot to update it before merging
> v6 from the list.
>
> Thanks,
> Lorenzo
>
> > >  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
> > > ...
> > >  static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
diff mbox series

Patch

diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index c20fd6b..94ba5c0 100644
--- a/drivers/pci/controller/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
@@ -1146,11 +1146,43 @@  static int iproc_pcie_setup_ib(struct iproc_pcie *pcie,
 	return ret;
 }
 
+static int
+iproc_pcie_add_dma_range(struct device *dev, struct list_head *resources,
+			 struct of_pci_range *range)
+{
+	struct resource *res;
+	struct resource_entry *entry, *tmp;
+	struct list_head *head = resources;
+
+	res = devm_kzalloc(dev, sizeof(struct resource), GFP_KERNEL);
+	if (!res)
+		return -ENOMEM;
+
+	resource_list_for_each_entry(tmp, resources) {
+		if (tmp->res->start < range->cpu_addr)
+			head = &tmp->node;
+	}
+
+	res->start = range->cpu_addr;
+	res->end = res->start + range->size - 1;
+
+	entry = resource_list_create_entry(res, 0);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->offset = res->start - range->cpu_addr;
+	resource_list_add(entry, head);
+
+	return 0;
+}
+
 static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
 {
+	struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
 	int ret;
+	LIST_HEAD(resources);
 
 	/* Get the dma-ranges from DT */
 	ret = of_pci_dma_range_parser_init(&parser, pcie->dev->of_node);
@@ -1158,13 +1190,23 @@  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
 		return ret;
 
 	for_each_of_pci_range(&parser, &range) {
+		ret = iproc_pcie_add_dma_range(pcie->dev,
+					       &resources,
+					       &range);
+		if (ret)
+			goto out;
 		/* Each range entry corresponds to an inbound mapping region */
 		ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM);
 		if (ret)
-			return ret;
+			goto out;
 	}
 
+	list_splice_init(&resources, &host->dma_ranges);
+
 	return 0;
+out:
+	pci_free_resource_list(&resources);
+	return ret;
 }
 
 static int iproce_pcie_get_msi(struct iproc_pcie *pcie,