Re: [PATCH v4 3/3] PCI/of fix of_dma_get_range; get PCI specific dma-ranges

2017-05-07 Thread kbuild test robot
Hi Oza,

[auto build test ERROR on v4.9-rc8]
[cannot apply to iommu/next next-20170505]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Oza-Pawandeep/OF-PCI-address-PCI-inbound-memory-limitations/20170507-141549
config: c6x-evmc6678_defconfig (attached as .config)
compiler: c6x-elf-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=c6x 

All errors (new ones prefixed by >>):

>> drivers/of/address.c:580:21: error: 'of_bus_isa_get_dma_ranges' undeclared 
>> here (not in a function)
  .get_dma_ranges = of_bus_isa_get_dma_ranges,
^
>> drivers/of/address.c:591:21: error: 'of_bus_default_get_dma_ranges' 
>> undeclared here (not in a function)
  .get_dma_ranges = of_bus_default_get_dma_ranges,
^

vim +/of_bus_isa_get_dma_ranges +580 drivers/of/address.c

   574  .addresses = "reg",
   575  .match = of_bus_isa_match,
   576  .count_cells = of_bus_isa_count_cells,
   577  .map = of_bus_isa_map,
   578  .translate = of_bus_isa_translate,
   579  .get_flags = of_bus_isa_get_flags,
 > 580  .get_dma_ranges = of_bus_isa_get_dma_ranges,
   581  },
   582  /* Default */
   583  {
   584  .name = "default",
   585  .addresses = "reg",
   586  .match = NULL,
   587  .count_cells = of_bus_default_count_cells,
   588  .map = of_bus_default_map,
   589  .translate = of_bus_default_translate,
   590  .get_flags = of_bus_default_get_flags,
 > 591  .get_dma_ranges = of_bus_default_get_dma_ranges,
   592  },
   593  };
   594  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 3/3] PCI/of fix of_dma_get_range; get PCI specific dma-ranges

2017-05-05 Thread Oza Pawandeep via iommu
current device framework and OF framework integration assumes
dma-ranges in a way where memory-mapped devices define their
dma-ranges. (child-bus-address, parent-bus-address, length).

of_dma_configure is specifically written to take care of memory
mapped devices. but no implementation exists for pci to take
care of pcie based memory ranges.

for e.g. iproc based SOCs and other SOCs(suc as rcar) have PCI
world dma-ranges.
dma-ranges = <0x4300 0x00 0x00 0x00 0x00 0x80 0x00>;

this patch fixes the bug in of_dma_get_range, which with as is,
parses the PCI memory ranges and return wrong size as 0.

in order to get largest possible dma_mask. this patch also
retuns the largest possible size based on dma-ranges,

for e.g.
dma-ranges = <0x4300 0x00 0x00 0x00 0x00 0x80 0x00>;
we should get dev->coherent_dma_mask=0x7f.

based on which IOVA allocation space will honour PCI host
bridge limitations.

the implementation hooks bus specific callbacks for getting
dma-ranges.

Signed-off-by: Oza Pawandeep 

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..b43e347 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -46,6 +47,8 @@ struct of_bus {
int na, int ns, int pna);
int (*translate)(__be32 *addr, u64 offset, int na);
unsigned int(*get_flags)(const __be32 *addr);
+   int (*get_dma_ranges)(struct device_node *np,
+ u64 *dma_addr, u64 *paddr, u64 *size);
 };
 
 /*
@@ -171,6 +174,144 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, 
int na)
 {
return of_bus_default_translate(addr + 1, offset, na - 1);
 }
+
+static int of_bus_pci_get_dma_ranges(struct device_node *np, u64 *dma_addr,
+u64 *paddr, u64 *size)
+{
+   struct device_node *node = of_node_get(np);
+   int ret = 0;
+   struct resource_entry *window;
+   LIST_HEAD(res);
+
+   if (!node)
+   return -EINVAL;
+
+   *size = 0;
+   /*
+* PCI dma-ranges is not mandatory property.
+* many devices do no need to have it, since
+* host bridge does not require inbound memory
+* configuration or rather have design limitations.
+* so we look for dma-ranges, if missing we
+* just return the caller full size, and also
+* no dma-ranges suggests that, host bridge allows
+* whatever comes in, so we set dma_addr to 0.
+*/
+   ret = of_pci_get_dma_ranges(np, );
+   if (!ret) {
+   resource_list_for_each_entry(window, ) {
+   struct resource *res_dma = window->res;
+
+   if (*size < resource_size(res_dma)) {
+   *dma_addr = res_dma->start - window->offset;
+   *paddr = res_dma->start;
+   *size = resource_size(res_dma);
+   }
+   }
+   }
+   pci_free_resource_list();
+
+   /*
+* return the largest possible size,
+* since PCI master allows everything.
+*/
+   if (*size == 0) {
+   pr_debug("empty/zero size dma-ranges found for node(%s)\n",
+   np->full_name);
+   *size = DMA_BIT_MASK(sizeof(dma_addr_t) * 8) - 1;
+   *dma_addr = *paddr = 0;
+   ret = 0;
+   }
+
+   pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
+*dma_addr, *paddr, *size);
+
+   of_node_put(node);
+
+   return ret;
+}
+
+static int get_dma_ranges(struct device_node *np, u64 *dma_addr,
+ u64 *paddr, u64 *size)
+{
+   struct device_node *node = of_node_get(np);
+   const __be32 *ranges = NULL;
+   int len, naddr, nsize, pna;
+   int ret = 0;
+   u64 dmaaddr;
+
+   if (!node)
+   return -EINVAL;
+
+   while (1) {
+   naddr = of_n_addr_cells(node);
+   nsize = of_n_size_cells(node);
+   node = of_get_next_parent(node);
+   if (!node)
+   break;
+
+   ranges = of_get_property(node, "dma-ranges", );
+
+   /* Ignore empty ranges, they imply no translation required */
+   if (ranges && len > 0)
+   break;
+
+   /*
+* At least empty ranges has to be defined for parent node if
+* DMA is supported
+*/
+   if (!ranges)
+   break;
+   }
+
+   if (!ranges) {
+   pr_debug("no dma-ranges found for node(%s)\n", np->full_name);
+   ret = -ENODEV;
+   goto out;
+   }
+
+   len /= sizeof(u32);
+
+   pna = of_n_addr_cells(node);
+
+   /* dma-ranges format:
+* DMA addr : naddr