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 |
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,
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,
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 --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,