summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut+renesas@gmail.com>2019-10-26 20:26:59 +0200
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2019-11-11 15:29:20 +0100
commit767c7846419cc562c9dd4f14cc617c2b9b1b96cd (patch)
tree063397a8f390a646387a3f96b21aff341cc6d145 /drivers/pci
parentPCI: rcar: Move the inbound index check (diff)
downloadlinux-767c7846419cc562c9dd4f14cc617c2b9b1b96cd.tar.xz
linux-767c7846419cc562c9dd4f14cc617c2b9b1b96cd.zip
PCI: rcar: Recalculate inbound range alignment for each controller entry
Due to hardware constraints, the size of each inbound range entry populated into the controller cannot be larger than the alignment of the entry's start address. Currently, the alignment for each "dma-ranges" inbound range is calculated only once for each range and the increment for programming the controller is also derived from it only once. Thus, a "dma-ranges" entry describing a memory at 0x48000000 and size 0x38000000 would lead to multiple controller entries, each 0x08000000 long. This is inefficient, especially considering that by adding the size to the start address, the alignment increases. This patch moves the alignment calculation into the loop populating the controller entries, thus updating the alignment for each controller entry. Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Andrew Murray <andrew.murray@arm.com> Reviewed-by: Simon Horman <horms+renesas@verge.net.au> Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Cc: Geert Uytterhoeven <geert+renesas@glider.be> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: Wolfram Sang <wsa@the-dreams.de> Cc: linux-renesas-soc@vger.kernel.org
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/controller/pcie-rcar.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
index 04ff6c4baa70..40d8c54a17d1 100644
--- a/drivers/pci/controller/pcie-rcar.c
+++ b/drivers/pci/controller/pcie-rcar.c
@@ -1027,30 +1027,31 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
if (restype & IORESOURCE_PREFETCH)
flags |= LAM_PREFETCH;
- /*
- * If the size of the range is larger than the alignment of the start
- * address, we have to use multiple entries to perform the mapping.
- */
- if (cpu_addr > 0) {
- unsigned long nr_zeros = __ffs64(cpu_addr);
- u64 alignment = 1ULL << nr_zeros;
-
- size = min(range->size, alignment);
- } else {
- size = range->size;
- }
- /* Hardware supports max 4GiB inbound region */
- size = min(size, 1ULL << 32);
-
- mask = roundup_pow_of_two(size) - 1;
- mask &= ~0xf;
-
while (cpu_addr < cpu_end) {
if (idx >= MAX_NR_INBOUND_MAPS - 1) {
dev_err(pcie->dev, "Failed to map inbound regions!\n");
return -EINVAL;
}
/*
+ * If the size of the range is larger than the alignment of
+ * the start address, we have to use multiple entries to
+ * perform the mapping.
+ */
+ if (cpu_addr > 0) {
+ unsigned long nr_zeros = __ffs64(cpu_addr);
+ u64 alignment = 1ULL << nr_zeros;
+
+ size = min(range->size, alignment);
+ } else {
+ size = range->size;
+ }
+ /* Hardware supports max 4GiB inbound region */
+ size = min(size, 1ULL << 32);
+
+ mask = roundup_pow_of_two(size) - 1;
+ mask &= ~0xf;
+
+ /*
* Set up 64-bit inbound regions as the range parser doesn't
* distinguish between 32 and 64-bit types.
*/