Re: [PATCH 1/2] ipr: Convert to generic DMA API

2014-10-21 Thread Christoph Hellwig
Wendy, Brian,

can you give me an ACK for this series?

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/2] ipr: Convert to generic DMA API

2014-10-30 Thread Christoph Hellwig
On Wed, Oct 29, 2014 at 12:34:49PM -0500, Brian King wrote:
> Acked-by: Brian King 

Doesn't apply to me.

Brain, can you please resend a rebased version of these two patches with
ipr error handlign patch (and anything else ipr related)?

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/3] ipr: Convert to generic DMA API

2014-11-03 Thread Christoph Hellwig
Thanks, I've applied patch 3 to drivers-for-3.18, and patches 1 and 2 to
core-for-3.19.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 01/31] scatterlist: add sg_pfn and sg_has_page helpers

2015-08-12 Thread Christoph Hellwig
Signed-off-by: Christoph Hellwig 
---
 include/linux/scatterlist.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 9b1ef0c..b1056bf 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -230,6 +230,16 @@ static inline dma_addr_t sg_phys(struct scatterlist *sg)
return page_to_phys(sg_page(sg)) + sg->offset;
 }
 
+static inline unsigned long sg_pfn(struct scatterlist *sg)
+{
+   return page_to_pfn(sg_page(sg));
+}
+
+static inline bool sg_has_page(struct scatterlist *sg)
+{
+   return true;
+}
+
 /**
  * sg_virt - Return virtual address of an sg entry
  * @sg:  SG entry
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 02/31] scatterlist: use sg_phys()

2015-08-12 Thread Christoph Hellwig
From: Dan Williams 

Coccinelle cleanup to replace open coded sg to physical address
translations.  This is in preparation for introducing scatterlists that
reference __pfn_t.

// sg_phys.cocci: convert usage page_to_phys(sg_page(sg)) to sg_phys(sg)
// usage: make coccicheck COCCI=sg_phys.cocci MODE=patch

virtual patch

@@
struct scatterlist *sg;
@@

- page_to_phys(sg_page(sg)) + sg->offset
+ sg_phys(sg)

@@
struct scatterlist *sg;
@@

- page_to_phys(sg_page(sg))
+ sg_phys(sg) & PAGE_MASK

Signed-off-by: Dan Williams 
---
 arch/arm/mm/dma-mapping.c| 2 +-
 arch/microblaze/kernel/dma.c | 3 +--
 drivers/iommu/intel-iommu.c  | 4 ++--
 drivers/iommu/iommu.c| 2 +-
 drivers/staging/android/ion/ion_chunk_heap.c | 4 ++--
 5 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index cba12f3..3d3d6aa 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1520,7 +1520,7 @@ static int __map_sg_chunk(struct device *dev, struct 
scatterlist *sg,
return -ENOMEM;
 
for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
-   phys_addr_t phys = page_to_phys(sg_page(s));
+   phys_addr_t phys = sg_phys(s) & PAGE_MASK;
unsigned int len = PAGE_ALIGN(s->offset + s->length);
 
if (!is_coherent &&
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index bf4dec2..c89da63 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -61,8 +61,7 @@ static int dma_direct_map_sg(struct device *dev, struct 
scatterlist *sgl,
/* FIXME this part of code is untested */
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg);
-   __dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
-   sg->length, direction);
+   __dma_sync(sg_phys(sg), sg->length, direction);
}
 
return nents;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 0649b94..3541d65 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2097,7 +2097,7 @@ static int __domain_mapping(struct dmar_domain *domain, 
unsigned long iov_pfn,
sg_res = aligned_nrpages(sg->offset, sg->length);
sg->dma_address = ((dma_addr_t)iov_pfn << 
VTD_PAGE_SHIFT) + sg->offset;
sg->dma_length = sg->length;
-   pteval = page_to_phys(sg_page(sg)) | prot;
+   pteval = (sg_phys(sg) & PAGE_MASK) | prot;
phys_pfn = pteval >> VTD_PAGE_SHIFT;
}
 
@@ -3623,7 +3623,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 
for_each_sg(sglist, sg, nelems, i) {
BUG_ON(!sg_page(sg));
-   sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
+   sg->dma_address = sg_phys(sg);
sg->dma_length = sg->length;
}
return nelems;
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index f286090..049df49 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1408,7 +1408,7 @@ size_t default_iommu_map_sg(struct iommu_domain *domain, 
unsigned long iova,
min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
 
for_each_sg(sg, s, nents, i) {
-   phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset;
+   phys_addr_t phys = sg_phys(s);
 
/*
 * We are mapping on IOMMU page boundaries, so offset within
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c 
b/drivers/staging/android/ion/ion_chunk_heap.c
index 5474615..f7b6ef9 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -81,7 +81,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap,
 err:
sg = table->sgl;
for (i -= 1; i >= 0; i--) {
-   gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
+   gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
  sg->length);
sg = sg_next(sg);
}
@@ -109,7 +109,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer)
DMA_BIDIRECTIONAL);
 
for_each_sg(table->sgl, sg, table->nents, i) {
-   gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
+   gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
  sg->length);
}
chunk_heap->allocated -= allocated_size;
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 04/31] x86/pci-nommu: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Just remove a BUG_ON, the code handles them just fine as-is.

Signed-off-by: Christoph Hellwig 
---
 arch/x86/kernel/pci-nommu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index da15918..a218059 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -63,7 +63,6 @@ static int nommu_map_sg(struct device *hwdev, struct 
scatterlist *sg,
WARN_ON(nents == 0 || sg[0].length == 0);
 
for_each_sg(sg, s, nents, i) {
-   BUG_ON(!sg_page(s));
s->dma_address = sg_phys(s);
if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
return 0;
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 03/31] dma-debug: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_pfn to get a the PFN and skip checks that require a kernel
virtual address.

Signed-off-by: Christoph Hellwig 
---
 lib/dma-debug.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index dace71f..a215a80 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -1368,7 +1368,7 @@ void debug_dma_map_sg(struct device *dev, struct 
scatterlist *sg,
 
entry->type   = dma_debug_sg;
entry->dev= dev;
-   entry->pfn= page_to_pfn(sg_page(s));
+   entry->pfn= sg_pfn(s);
entry->offset = s->offset,
entry->size   = sg_dma_len(s);
entry->dev_addr   = sg_dma_address(s);
@@ -1376,7 +1376,7 @@ void debug_dma_map_sg(struct device *dev, struct 
scatterlist *sg,
entry->sg_call_ents   = nents;
entry->sg_mapped_ents = mapped_ents;
 
-   if (!PageHighMem(sg_page(s))) {
+   if (sg_has_page(s) && !PageHighMem(sg_page(s))) {
check_for_stack(dev, sg_virt(s));
check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s));
}
@@ -1419,7 +1419,7 @@ void debug_dma_unmap_sg(struct device *dev, struct 
scatterlist *sglist,
struct dma_debug_entry ref = {
.type   = dma_debug_sg,
.dev= dev,
-   .pfn= page_to_pfn(sg_page(s)),
+   .pfn= sg_pfn(s),
.offset = s->offset,
.dev_addr   = sg_dma_address(s),
.size   = sg_dma_len(s),
@@ -1580,7 +1580,7 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct 
scatterlist *sg,
struct dma_debug_entry ref = {
.type   = dma_debug_sg,
.dev= dev,
-   .pfn= page_to_pfn(sg_page(s)),
+   .pfn= sg_pfn(s),
.offset = s->offset,
.dev_addr   = sg_dma_address(s),
.size   = sg_dma_len(s),
@@ -1613,7 +1613,7 @@ void debug_dma_sync_sg_for_device(struct device *dev, 
struct scatterlist *sg,
struct dma_debug_entry ref = {
.type   = dma_debug_sg,
.dev= dev,
-   .pfn= page_to_pfn(sg_page(s)),
+   .pfn= sg_pfn(s),
.offset = s->offset,
.dev_addr   = sg_dma_address(s),
.size   = sg_dma_len(s),
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

RFC: prepare for struct scatterlist entries without page backing

2015-08-12 Thread Christoph Hellwig
Dan Williams started to look into addressing I/O to and from
Persistent Memory in his series from June:

http://thread.gmane.org/gmane.linux.kernel.cross-arch/27944

I've started looking into DMA mapping of these SGLs specifically instead
of the map_pfn method in there.  In addition to supporting NVDIMM backed
I/O I also suspect this would be highly useful for media drivers that
go through nasty hoops to be able to DMA from/to their ioremapped regions,
with vb2_dc_get_userptr in drivers/media/v4l2-core/videobuf2-dma-contig.c
being a prime example for the unsafe hacks currently used.

It turns out most DMA mapping implementation can handle SGLs without
page structures with some fairly simple mechanical work.  Most of it
is just about consistently using sg_phys.  For implementations that
need to flush caches we need a new helper that skips these cache
flushes if a entry doesn't have a kernel virtual address.

However the ccio (parisc) and sba_iommu (parisc & ia64) IOMMUs seem
to be operate mostly on virtual addresses.  It's a fairly odd concept
that I don't fully grasp, so I'll need some help with those if we want
to bring this forward.

Additional this series skips ARM entirely for now.  The reason is
that most arm implementations of the .map_sg operation just iterate
over all entries and call ->map_page for it, which means we'd need
to convert those to a ->map_pfn similar to Dan's previous approach.

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 05/31] x86/pci-calgary: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
For the iommu offset we just need and offset into the page.  Calculate
that using the physical address instead of using the virtual address
so that we don't require a virtual mapping.

Signed-off-by: Christoph Hellwig 
---
 arch/x86/kernel/pci-calgary_64.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 0497f71..8f1581d 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -368,16 +368,14 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
 {
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
-   unsigned long vaddr;
+   unsigned long paddr;
unsigned int npages;
unsigned long entry;
int i;
 
for_each_sg(sg, s, nelems, i) {
-   BUG_ON(!sg_page(s));
-
-   vaddr = (unsigned long) sg_virt(s);
-   npages = iommu_num_pages(vaddr, s->length, PAGE_SIZE);
+   paddr = sg_phys(s);
+   npages = iommu_num_pages(paddr, s->length, PAGE_SIZE);
 
entry = iommu_range_alloc(dev, tbl, npages);
if (entry == DMA_ERROR_CODE) {
@@ -389,7 +387,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
s->dma_address = (entry << PAGE_SHIFT) | s->offset;
 
/* insert into HW table */
-   tce_build(tbl, entry, npages, vaddr & PAGE_MASK, dir);
+   tce_build(tbl, entry, npages, paddr & PAGE_MASK, dir);
 
s->dma_length = s->length;
}
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 06/31] alpha/pci-noop: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_phys() instead of virt_to_phys(sg_virt(sg)) so that we don't
require a kernel virtual address.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/kernel/pci-noop.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index df24b76..7319151 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -145,11 +145,7 @@ static int alpha_noop_map_sg(struct device *dev, struct 
scatterlist *sgl, int ne
struct scatterlist *sg;
 
for_each_sg(sgl, sg, nents, i) {
-   void *va;
-
-   BUG_ON(!sg_page(sg));
-   va = sg_virt(sg);
-   sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
+   sg_dma_address(sg) = (dma_addr_t)sg_phys(sg);
sg_dma_len(sg) = sg->length;
}
 
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 07/31] alpha/pci_iommu: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_phys() instead of virt_to_phys(sg_virt(sg)) so that we don't
require a kernel virtual address, and switch a few debug printfs to
print physical instead of virtual addresses.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/kernel/pci_iommu.c | 36 +++-
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index eddee77..5d46b49 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -248,20 +248,17 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 
mask)
until either pci_unmap_single or pci_dma_sync_single is performed.  */
 
 static dma_addr_t
-pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
+pci_map_single_1(struct pci_dev *pdev, unsigned long paddr, size_t size,
 int dac_allowed)
 {
struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
struct pci_iommu_arena *arena;
long npages, dma_ofs, i;
-   unsigned long paddr;
dma_addr_t ret;
unsigned int align = 0;
struct device *dev = pdev ? &pdev->dev : NULL;
 
-   paddr = __pa(cpu_addr);
-
 #if !DEBUG_NODIRECT
/* First check to see if we can use the direct map window.  */
if (paddr + size + __direct_map_base - 1 <= max_dma
@@ -269,7 +266,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, 
size_t size,
ret = paddr + __direct_map_base;
 
DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %pf\n",
- cpu_addr, size, ret, __builtin_return_address(0));
+ paddr, size, ret, __builtin_return_address(0));
 
return ret;
}
@@ -280,7 +277,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, 
size_t size,
ret = paddr + alpha_mv.pci_dac_offset;
 
DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %pf\n",
- cpu_addr, size, ret, __builtin_return_address(0));
+ paddr, size, ret, __builtin_return_address(0));
 
return ret;
}
@@ -309,15 +306,15 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, 
size_t size,
return 0;
}
 
+   offset = paddr & ~PAGE_MASK;
paddr &= PAGE_MASK;
for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
 
-   ret = arena->dma_base + dma_ofs * PAGE_SIZE;
-   ret += (unsigned long)cpu_addr & ~PAGE_MASK;
+   ret = arena->dma_base + dma_ofs * PAGE_SIZE + offset;
 
DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %pf\n",
- cpu_addr, size, npages, ret, __builtin_return_address(0));
+ paddr, size, npages, ret, __builtin_return_address(0));
 
return ret;
 }
@@ -357,7 +354,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, 
struct page *page,
BUG_ON(dir == PCI_DMA_NONE);
 
dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
-   return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
+   return pci_map_single_1(pdev, page_to_phys(page) + offset,
size, dac_allowed);
 }
 
@@ -453,7 +450,7 @@ try_again:
}
memset(cpu_addr, 0, size);
 
-   *dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
+   *dma_addrp = pci_map_single_1(pdev, __pa(cpu_addr), size, 0);
if (*dma_addrp == 0) {
free_pages((unsigned long)cpu_addr, order);
if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
@@ -497,9 +494,6 @@ static void alpha_pci_free_coherent(struct device *dev, 
size_t size,
Write dma_length of each leader with the combined lengths of
the mergable followers.  */
 
-#define SG_ENT_VIRT_ADDRESS(SG) (sg_virt((SG)))
-#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
-
 static void
 sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist 
*end,
int virt_ok)
@@ -512,13 +506,13 @@ sg_classify(struct device *dev, struct scatterlist *sg, 
struct scatterlist *end,
leader = sg;
leader_flag = 0;
leader_length = leader->length;
-   next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
+   next_paddr = sg_phys(leader) + leader_length;
 
/* we will not marge sg without device. */
max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
for (++sg; sg < end; ++sg) {
unsigned long addr, len;
-   addr = SG_ENT_PHYS_ADDRESS(sg);
+   addr = sg_phys(sg);
len = sg->length;
 
if (leader_length + len > max_seg_size)
@@ -555,7 +549,7 @@ sg_fill(struct device *dev, struct scatte

[PATCH 08/31] c6x: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_phys() instead of virt_to_phys(sg_virt(sg)) so that we don't
require a kernel virtual address.

Signed-off-by: Christoph Hellwig 
---
 arch/c6x/kernel/dma.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/c6x/kernel/dma.c b/arch/c6x/kernel/dma.c
index ab7b12d..79cae03 100644
--- a/arch/c6x/kernel/dma.c
+++ b/arch/c6x/kernel/dma.c
@@ -68,8 +68,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist,
int i;
 
for_each_sg(sglist, sg, nents, i)
-   sg->dma_address = dma_map_single(dev, sg_virt(sg), sg->length,
-dir);
+   sg->dma_address = sg_phys(sg);
 
debug_dma_map_sg(dev, sglist, nents, nents, dir);
 
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 09/31] ia64/pci_dma: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_phys() instead of virt_to_phys(sg_virt(sg)) so that we don't
require a kernel virtual address.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/sn/pci/pci_dma.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index d0853e8..8f713c8 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -18,9 +18,6 @@
 #include 
 #include 
 
-#define SG_ENT_VIRT_ADDRESS(sg)(sg_virt((sg)))
-#define SG_ENT_PHYS_ADDRESS(SG)virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
-
 /**
  * sn_dma_supported - test a DMA mask
  * @dev: device to test
@@ -291,7 +288,7 @@ static int sn_dma_map_sg(struct device *dev, struct 
scatterlist *sgl,
 */
for_each_sg(sgl, sg, nhwentries, i) {
dma_addr_t dma_addr;
-   phys_addr = SG_ENT_PHYS_ADDRESS(sg);
+   phys_addr = sg_phys(sg);
if (dmabarr)
dma_addr = provider->dma_map_consistent(pdev,
phys_addr,
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 10/31] powerpc/iommu: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
For the iommu offset we just need and offset into the page.  Calculate
that using the physical address instead of using the virtual address
so that we don't require a virtual mapping.

Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/kernel/iommu.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index a8e3490..0f52e40 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -457,7 +457,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table 
*tbl,
 
max_seg_size = dma_get_max_seg_size(dev);
for_each_sg(sglist, s, nelems, i) {
-   unsigned long vaddr, npages, entry, slen;
+   unsigned long paddr, npages, entry, slen;
 
slen = s->length;
/* Sanity check */
@@ -466,22 +466,22 @@ int ppc_iommu_map_sg(struct device *dev, struct 
iommu_table *tbl,
continue;
}
/* Allocate iommu entries for that segment */
-   vaddr = (unsigned long) sg_virt(s);
-   npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE(tbl));
+   paddr = sg_phys(s);
+   npages = iommu_num_pages(paddr, slen, IOMMU_PAGE_SIZE(tbl));
align = 0;
if (tbl->it_page_shift < PAGE_SHIFT && slen >= PAGE_SIZE &&
-   (vaddr & ~PAGE_MASK) == 0)
+   (paddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - tbl->it_page_shift;
entry = iommu_range_alloc(dev, tbl, npages, &handle,
  mask >> tbl->it_page_shift, align);
 
-   DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
+   DBG("  - paddr: %lx, size: %lx\n", paddr, slen);
 
/* Handle failure */
if (unlikely(entry == DMA_ERROR_CODE)) {
if (printk_ratelimit())
dev_info(dev, "iommu_alloc failed, tbl %p "
-"vaddr %lx npages %lu\n", tbl, vaddr,
+"paddr %lx npages %lu\n", tbl, paddr,
 npages);
goto failure;
}
@@ -496,7 +496,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table 
*tbl,
 
/* Insert into HW table */
build_fail = tbl->it_ops->set(tbl, entry, npages,
- vaddr & IOMMU_PAGE_MASK(tbl),
+ paddr & IOMMU_PAGE_MASK(tbl),
  direction, attrs);
if(unlikely(build_fail))
goto failure;
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 11/31] sparc/iommu: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_phys() instead of __pa(sg_virt(sg)) so that we don't
require a kernel virtual address.

Signed-off-by: Christoph Hellwig 
---
 arch/sparc/kernel/iommu.c| 2 +-
 arch/sparc/kernel/iommu_common.h | 4 +---
 arch/sparc/kernel/pci_sun4v.c| 2 +-
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 5320689..2ad89d2 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -486,7 +486,7 @@ static int dma_4u_map_sg(struct device *dev, struct 
scatterlist *sglist,
continue;
}
/* Allocate iommu entries for that segment */
-   paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+   paddr = sg_phys(s);
npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
entry = iommu_tbl_range_alloc(dev, &iommu->tbl, npages,
  &handle, (unsigned long)(-1), 0);
diff --git a/arch/sparc/kernel/iommu_common.h b/arch/sparc/kernel/iommu_common.h
index b40cec2..8e2c211 100644
--- a/arch/sparc/kernel/iommu_common.h
+++ b/arch/sparc/kernel/iommu_common.h
@@ -33,15 +33,13 @@
  */
 #define IOMMU_PAGE_SHIFT   13
 
-#define SG_ENT_PHYS_ADDRESS(SG)(__pa(sg_virt((SG
-
 static inline int is_span_boundary(unsigned long entry,
   unsigned long shift,
   unsigned long boundary_size,
   struct scatterlist *outs,
   struct scatterlist *sg)
 {
-   unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs);
+   unsigned long paddr = sg_phys(outs);
int nr = iommu_num_pages(paddr, outs->dma_length + sg->length,
 IO_PAGE_SIZE);
 
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index d2fe57d..a7a6e41 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -370,7 +370,7 @@ static int dma_4v_map_sg(struct device *dev, struct 
scatterlist *sglist,
continue;
}
/* Allocate iommu entries for that segment */
-   paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+   paddr = sg_phys(s);
npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
entry = iommu_tbl_range_alloc(dev, &iommu->tbl, npages,
  &handle, (unsigned long)(-1), 0);
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 12/31] mn10300: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Just remove a BUG_ON, the code handles them just fine as-is.

Signed-off-by: Christoph Hellwig 
---
 arch/mn10300/include/asm/dma-mapping.h | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/mn10300/include/asm/dma-mapping.h 
b/arch/mn10300/include/asm/dma-mapping.h
index a18abfc..b1b1050 100644
--- a/arch/mn10300/include/asm/dma-mapping.h
+++ b/arch/mn10300/include/asm/dma-mapping.h
@@ -57,11 +57,8 @@ int dma_map_sg(struct device *dev, struct scatterlist 
*sglist, int nents,
BUG_ON(!valid_dma_direction(direction));
WARN_ON(nents == 0 || sglist[0].length == 0);
 
-   for_each_sg(sglist, sg, nents, i) {
-   BUG_ON(!sg_page(sg));
-
+   for_each_sg(sglist, sg, nents, i)
sg->dma_address = sg_phys(sg);
-   }
 
mn10300_dcache_flush_inv();
return nents;
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 13/31] sparc/ldc: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use

sg_phys(sg) & PAGE_MASK

instead of

page_to_pfn(sg_page(sg)) << PAGE_SHIFT

to get at the page-aligned physical address ofa SG entry, so that
we don't require a page backing for SG entries.

Signed-off-by: Christoph Hellwig 
---
 arch/sparc/kernel/ldc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index 1ae5eb1..0a29974 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -2051,7 +2051,7 @@ static void fill_cookies(struct cookie_state *sp, 
unsigned long pa,
 
 static int sg_count_one(struct scatterlist *sg)
 {
-   unsigned long base = page_to_pfn(sg_page(sg)) << PAGE_SHIFT;
+   unsigned long base = sg_phys(sg) & PAGE_MASK;
long len = sg->length;
 
if ((sg->offset | len) & (8UL - 1))
@@ -2114,7 +2114,7 @@ int ldc_map_sg(struct ldc_channel *lp,
state.nc = 0;
 
for_each_sg(sg, s, num_sg, i) {
-   fill_cookies(&state, page_to_pfn(sg_page(s)) << PAGE_SHIFT,
+   fill_cookies(&state, sg_phys(s) & PAGE_MASK,
 s->offset, s->length);
}
 
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 14/31] sparc32/io-unit: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
For the iommu offset we just need and offset into the page.  Calculate
that using the physical address instead of using the virtual address
so that we don't require a virtual mapping.

Signed-off-by: Christoph Hellwig 
---
 arch/sparc/mm/io-unit.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index f311bf2..82f97ae 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -91,13 +91,14 @@ static int __init iounit_init(void)
 subsys_initcall(iounit_init);
 
 /* One has to hold iounit->lock to call this */
-static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned 
long vaddr, int size)
+static dma_addr_t iounit_get_area(struct iounit_struct *iounit,
+   unsigned long paddr, int size)
 {
int i, j, k, npages;
-   unsigned long rotor, scan, limit;
+   unsigned long rotor, scan, limit, dma_addr;
iopte_t iopte;
 
-npages = ((vaddr & ~PAGE_MASK) + size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
+npages = ((paddr & ~PAGE_MASK) + size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
 
/* A tiny bit of magic ingredience :) */
switch (npages) {
@@ -106,7 +107,7 @@ static unsigned long iounit_get_area(struct iounit_struct 
*iounit, unsigned long
default: i = 0x0213; break;
}

-   IOD(("iounit_get_area(%08lx,%d[%d])=", vaddr, size, npages));
+   IOD(("iounit_get_area(%08lx,%d[%d])=", paddr, size, npages));

 next:  j = (i & 15);
rotor = iounit->rotor[j - 1];
@@ -121,7 +122,7 @@ nexti:  scan = find_next_zero_bit(iounit->bmap, limit, 
scan);
}
i >>= 4;
if (!(i & 15))
-   panic("iounit_get_area: Couldn't find free iopte slots 
for (%08lx,%d)\n", vaddr, size);
+   panic("iounit_get_area: Couldn't find free iopte slots 
for (%08lx,%d)\n", paddr, size);
goto next;
}
for (k = 1, scan++; k < npages; k++)
@@ -129,14 +130,14 @@ nexti:scan = find_next_zero_bit(iounit->bmap, limit, 
scan);
goto nexti;
iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
scan -= npages;
-   iopte = MKIOPTE(__pa(vaddr & PAGE_MASK));
-   vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
+   iopte = MKIOPTE(paddr & PAGE_MASK);
+   dma_addr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (paddr & 
~PAGE_MASK);
for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), 
scan++) {
set_bit(scan, iounit->bmap);
sbus_writel(iopte, &iounit->page_table[scan]);
}
-   IOD(("%08lx\n", vaddr));
-   return vaddr;
+   IOD(("%08lx\n", dma_addr));
+   return dma_addr;
 }
 
 static __u32 iounit_get_scsi_one(struct device *dev, char *vaddr, unsigned 
long len)
@@ -145,7 +146,7 @@ static __u32 iounit_get_scsi_one(struct device *dev, char 
*vaddr, unsigned long
unsigned long ret, flags;

spin_lock_irqsave(&iounit->lock, flags);
-   ret = iounit_get_area(iounit, (unsigned long)vaddr, len);
+   ret = iounit_get_area(iounit, virt_to_phys(vaddr), len);
spin_unlock_irqrestore(&iounit->lock, flags);
return ret;
 }
@@ -159,7 +160,7 @@ static void iounit_get_scsi_sgl(struct device *dev, struct 
scatterlist *sg, int
spin_lock_irqsave(&iounit->lock, flags);
while (sz != 0) {
--sz;
-   sg->dma_address = iounit_get_area(iounit, (unsigned long) 
sg_virt(sg), sg->length);
+   sg->dma_address = iounit_get_area(iounit, sg_phys(sg), 
sg->length);
sg->dma_length = sg->length;
sg = sg_next(sg);
}
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 15/31] sparc32/iommu: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Pass a PFN to iommu_get_one instad of calculating it locall from a
page structure so that we don't need pages for every address we can
DMA to or from.

Also further restrict the cache flushing as we now have a non-highmem
way of not kernel virtual mapped physical addresses.

Signed-off-by: Christoph Hellwig 
---
 arch/sparc/mm/iommu.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 491511d..3ed53d7 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -174,7 +174,7 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int 
niopte)
}
 }
 
-static u32 iommu_get_one(struct device *dev, struct page *page, int npages)
+static u32 iommu_get_one(struct device *dev, unsigned long pfn, int npages)
 {
struct iommu_struct *iommu = dev->archdata.iommu;
int ioptex;
@@ -183,7 +183,7 @@ static u32 iommu_get_one(struct device *dev, struct page 
*page, int npages)
int i;
 
/* page color = pfn of page */
-   ioptex = bit_map_string_get(&iommu->usemap, npages, page_to_pfn(page));
+   ioptex = bit_map_string_get(&iommu->usemap, npages, pfn);
if (ioptex < 0)
panic("iommu out");
busa0 = iommu->start + (ioptex << PAGE_SHIFT);
@@ -192,11 +192,11 @@ static u32 iommu_get_one(struct device *dev, struct page 
*page, int npages)
busa = busa0;
iopte = iopte0;
for (i = 0; i < npages; i++) {
-   iopte_val(*iopte) = MKIOPTE(page_to_pfn(page), IOPERM);
+   iopte_val(*iopte) = MKIOPTE(pfn, IOPERM);
iommu_invalidate_page(iommu->regs, busa);
busa += PAGE_SIZE;
iopte++;
-   page++;
+   pfn++;
}
 
iommu_flush_iotlb(iopte0, npages);
@@ -214,7 +214,7 @@ static u32 iommu_get_scsi_one(struct device *dev, char 
*vaddr, unsigned int len)
off = (unsigned long)vaddr & ~PAGE_MASK;
npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT;
page = virt_to_page((unsigned long)vaddr & PAGE_MASK);
-   busa = iommu_get_one(dev, page, npages);
+   busa = iommu_get_one(dev, page_to_pfn(page), npages);
return busa + off;
 }
 
@@ -243,7 +243,7 @@ static void iommu_get_scsi_sgl_gflush(struct device *dev, 
struct scatterlist *sg
while (sz != 0) {
--sz;
n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
-   sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + 
sg->offset;
+   sg->dma_address = iommu_get_one(dev, sg_pfn(sg), n) + 
sg->offset;
sg->dma_length = sg->length;
sg = sg_next(sg);
}
@@ -264,7 +264,8 @@ static void iommu_get_scsi_sgl_pflush(struct device *dev, 
struct scatterlist *sg
 * XXX Is this a good assumption?
 * XXX What if someone else unmaps it here and races us?
 */
-   if ((page = (unsigned long) page_address(sg_page(sg))) != 0) {
+   if (sg_has_page(sg) &&
+   (page = (unsigned long) page_address(sg_page(sg))) != 0) {
for (i = 0; i < n; i++) {
if (page != oldpage) {  /* Already flushed? */
flush_page_for_dma(page);
@@ -274,7 +275,7 @@ static void iommu_get_scsi_sgl_pflush(struct device *dev, 
struct scatterlist *sg
}
}
 
-   sg->dma_address = iommu_get_one(dev, sg_page(sg), n) + 
sg->offset;
+   sg->dma_address = iommu_get_one(dev, sg_pfn(sg), n) + 
sg->offset;
sg->dma_length = sg->length;
sg = sg_next(sg);
}
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 16/31] s390: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Use sg_phys() instead of page_to_phys(sg_page(sg)) so that we don't
require a page structure for all DMA memory.

Signed-off-by: Christoph Hellwig 
---
 arch/s390/pci/pci_dma.c | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 6fd8d58..aae5a47 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -272,14 +272,13 @@ int dma_set_mask(struct device *dev, u64 mask)
 }
 EXPORT_SYMBOL_GPL(dma_set_mask);
 
-static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
-unsigned long offset, size_t size,
+static dma_addr_t s390_dma_map_phys(struct device *dev, unsigned long pa,
+size_t size,
 enum dma_data_direction direction,
 struct dma_attrs *attrs)
 {
struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
unsigned long nr_pages, iommu_page_index;
-   unsigned long pa = page_to_phys(page) + offset;
int flags = ZPCI_PTE_VALID;
dma_addr_t dma_addr;
 
@@ -301,7 +300,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, 
struct page *page,
 
if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) {
atomic64_add(nr_pages, &zdev->mapped_pages);
-   return dma_addr + (offset & ~PAGE_MASK);
+   return dma_addr + (pa & ~PAGE_MASK);
}
 
 out_free:
@@ -312,6 +311,16 @@ out_err:
return DMA_ERROR_CODE;
 }
 
+static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
+unsigned long offset, size_t size,
+enum dma_data_direction direction,
+struct dma_attrs *attrs)
+{
+   unsigned long pa = page_to_phys(page) + offset;
+
+   return s390_dma_map_phys(dev, pa, size, direction, attrs);
+}
+
 static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
 size_t size, enum dma_data_direction direction,
 struct dma_attrs *attrs)
@@ -384,8 +393,7 @@ static int s390_dma_map_sg(struct device *dev, struct 
scatterlist *sg,
int i;
 
for_each_sg(sg, s, nr_elements, i) {
-   struct page *page = sg_page(s);
-   s->dma_address = s390_dma_map_pages(dev, page, s->offset,
+   s->dma_address = s390_dma_map_phys(dev, sg_phys(s),
s->length, dir, NULL);
if (!dma_mapping_error(dev, s->dma_address)) {
s->dma_length = s->length;
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 17/31] ia64/sba_iommu: remove sba_sg_address

2015-08-12 Thread Christoph Hellwig
Signed-off-by: Christoph Hellwig 
---
 arch/ia64/hp/common/sba_iommu.c | 22 ++
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 344387a..9e5aa8e 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -248,8 +248,6 @@ static int reserve_sba_gart = 1;
 static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t);
 static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t);
 
-#define sba_sg_address(sg) sg_virt((sg))
-
 #ifdef FULL_VALID_PDIR
 static u64 prefetch_spill_page;
 #endif
@@ -397,7 +395,7 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, 
int nents)
while (nents-- > 0) {
printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents,
   startsg->dma_address, startsg->dma_length,
-  sba_sg_address(startsg));
+  sg_virt(startsg));
startsg = sg_next(startsg);
}
 }
@@ -409,7 +407,7 @@ sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, 
int nents)
int the_nents = nents;
 
while (the_nents-- > 0) {
-   if (sba_sg_address(the_sg) == 0x0UL)
+   if (sg_virt(the_sg) == 0x0UL)
sba_dump_sg(NULL, startsg, nents);
the_sg = sg_next(the_sg);
}
@@ -1243,11 +1241,11 @@ sba_fill_pdir(
if (dump_run_sg)
printk(" %2d : %08lx/%05x %p\n",
nents, startsg->dma_address, cnt,
-   sba_sg_address(startsg));
+   sg_virt(startsg));
 #else
DBG_RUN_SG(" %d : %08lx/%05x %p\n",
nents, startsg->dma_address, cnt,
-   sba_sg_address(startsg));
+   sg_virt(startsg));
 #endif
/*
** Look for the start of a new DMA stream
@@ -1267,7 +1265,7 @@ sba_fill_pdir(
** Look for a VCONTIG chunk
*/
if (cnt) {
-   unsigned long vaddr = (unsigned long) 
sba_sg_address(startsg);
+   unsigned long vaddr = (unsigned long) sg_virt(startsg);
ASSERT(pdirp);
 
/* Since multiple Vcontig blocks could make up
@@ -1335,7 +1333,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
int idx;
 
while (nents > 0) {
-   unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
+   unsigned long vaddr = (unsigned long) sg_virt(startsg);
 
/*
** Prepare for first/next DMA stream
@@ -1380,7 +1378,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
**
** append the next transaction?
*/
-   vaddr = (unsigned long) sba_sg_address(startsg);
+   vaddr = (unsigned long) sg_virt(startsg);
if  (vcontig_end == vaddr)
{
vcontig_len += startsg->length;
@@ -1479,7 +1477,7 @@ static int sba_map_sg_attrs(struct device *dev, struct 
scatterlist *sglist,
if (likely((ioc->dma_mask & ~to_pci_dev(dev)->dma_mask) == 0)) {
for_each_sg(sglist, sg, nents, filled) {
sg->dma_length = sg->length;
-   sg->dma_address = virt_to_phys(sba_sg_address(sg));
+   sg->dma_address = virt_to_phys(sg_virt(sg));
}
return filled;
}
@@ -1487,7 +1485,7 @@ static int sba_map_sg_attrs(struct device *dev, struct 
scatterlist *sglist,
/* Fast path single entry scatterlists. */
if (nents == 1) {
sglist->dma_length = sglist->length;
-   sglist->dma_address = sba_map_single_attrs(dev, 
sba_sg_address(sglist), sglist->length, dir, attrs);
+   sglist->dma_address = sba_map_single_attrs(dev, 
sg_virt(sglist), sglist->length, dir, attrs);
return 1;
}
 
@@ -1563,7 +1561,7 @@ static void sba_unmap_sg_attrs(struct device *dev, struct 
scatterlist *sglist,
 #endif
 
DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
-  __func__, nents, sba_sg_address(sglist), sglist->length);
+  __func__, nents, sg_virt(sglist), sglist->length);
 
 #ifdef ASSERT_PDIR_SANITY
ioc = GET_IOC(dev);
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 18/31] nios2: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page() and use
sg_phys to get the physical address directly.

Signed-off-by: Christoph Hellwig 
---
 arch/nios2/mm/dma-mapping.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/arch/nios2/mm/dma-mapping.c b/arch/nios2/mm/dma-mapping.c
index ac5da75..1a0a68d 100644
--- a/arch/nios2/mm/dma-mapping.c
+++ b/arch/nios2/mm/dma-mapping.c
@@ -64,13 +64,11 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, 
int nents,
BUG_ON(!valid_dma_direction(direction));
 
for_each_sg(sg, sg, nents, i) {
-   void *addr;
-
-   addr = sg_virt(sg);
-   if (addr) {
-   __dma_sync_for_device(addr, sg->length, direction);
-   sg->dma_address = sg_phys(sg);
+   if (sg_has_page(sg)) {
+   __dma_sync_for_device(sg_virt(sg), sg->length,
+   direction);
}
+   sg->dma_address = sg_phys(sg);
}
 
return nents;
@@ -113,9 +111,8 @@ void dma_unmap_sg(struct device *dev, struct scatterlist 
*sg, int nhwentries,
return;
 
for_each_sg(sg, sg, nhwentries, i) {
-   addr = sg_virt(sg);
-   if (addr)
-   __dma_sync_for_cpu(addr, sg->length, direction);
+   if (sg_has_page(sg))
+   __dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
}
 }
 EXPORT_SYMBOL(dma_unmap_sg);
@@ -166,8 +163,10 @@ void dma_sync_sg_for_cpu(struct device *dev, struct 
scatterlist *sg, int nelems,
BUG_ON(!valid_dma_direction(direction));
 
/* Make sure that gcc doesn't leave the empty loop body.  */
-   for_each_sg(sg, sg, nelems, i)
-   __dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
+   for_each_sg(sg, sg, nelems, i) {
+   if (sg_has_page(sg))
+   __dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
+   }
 }
 EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
@@ -179,8 +178,10 @@ void dma_sync_sg_for_device(struct device *dev, struct 
scatterlist *sg,
BUG_ON(!valid_dma_direction(direction));
 
/* Make sure that gcc doesn't leave the empty loop body.  */
-   for_each_sg(sg, sg, nelems, i)
-   __dma_sync_for_device(sg_virt(sg), sg->length, direction);
-
+   for_each_sg(sg, sg, nelems, i) {
+   if (sg_has_page(sg))
+   __dma_sync_for_device(sg_virt(sg), sg->length,
+   direction);
+   }
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 19/31] arc: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page() and use
sg_phys to get the physical address directly.

Signed-off-by: Christoph Hellwig 
---
 arch/arc/include/asm/dma-mapping.h | 26 +++---
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arc/include/asm/dma-mapping.h 
b/arch/arc/include/asm/dma-mapping.h
index 2d28ba9..42eb526 100644
--- a/arch/arc/include/asm/dma-mapping.h
+++ b/arch/arc/include/asm/dma-mapping.h
@@ -108,9 +108,13 @@ dma_map_sg(struct device *dev, struct scatterlist *sg,
struct scatterlist *s;
int i;
 
-   for_each_sg(sg, s, nents, i)
-   s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
-  s->length, dir);
+   for_each_sg(sg, s, nents, i) {
+   if (sg_has_page(s)) {
+   _dma_cache_sync((unsigned long)sg_virt(s), s->length,
+   dir);
+   }
+   s->dma_address = sg_phys(s);
+   }
 
return nents;
 }
@@ -163,8 +167,12 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist 
*sglist, int nelems,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nelems, i)
-   _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
+   for_each_sg(sglist, sg, nelems, i) {
+   if (sg_has_page(sg)) {
+   _dma_cache_sync((unsigned int)sg_virt(sg), sg->length,
+   dir);
+   }
+   }
 }
 
 static inline void
@@ -174,8 +182,12 @@ dma_sync_sg_for_device(struct device *dev, struct 
scatterlist *sglist,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nelems, i)
-   _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
+   for_each_sg(sglist, sg, nelems, i) {
+   if (sg_has_page(sg)) {
+   _dma_cache_sync((unsigned int)sg_virt(sg), sg->length,
+   dir);
+   }
+   }
 }
 
 static inline int dma_supported(struct device *dev, u64 dma_mask)
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 20/31] avr32: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page() and use
sg_phys to get the physical address directly, bypassing the noop
page_to_bus.

Signed-off-by: Christoph Hellwig 
---
 arch/avr32/include/asm/dma-mapping.h | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/avr32/include/asm/dma-mapping.h 
b/arch/avr32/include/asm/dma-mapping.h
index ae7ac92..a662ce2 100644
--- a/arch/avr32/include/asm/dma-mapping.h
+++ b/arch/avr32/include/asm/dma-mapping.h
@@ -216,11 +216,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sglist, 
int nents,
struct scatterlist *sg;
 
for_each_sg(sglist, sg, nents, i) {
-   char *virt;
-
-   sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset;
-   virt = sg_virt(sg);
-   dma_cache_sync(dev, virt, sg->length, direction);
+   sg->dma_address = sg_phys(sg);
+   if (sg_has_page(sg))
+   dma_cache_sync(dev, sg_virt(sg), sg->length, direction);
}
 
return nents;
@@ -328,8 +326,10 @@ dma_sync_sg_for_device(struct device *dev, struct 
scatterlist *sglist,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nents, i)
-   dma_cache_sync(dev, sg_virt(sg), sg->length, direction);
+   for_each_sg(sglist, sg, nents, i) {
+   if (sg_has_page(sg))
+   dma_cache_sync(dev, sg_virt(sg), sg->length, direction);
+   }
 }
 
 /* Now for the API extensions over the pci_ one */
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 21/31] blackfin: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Switch from sg_virt to sg_phys as blackfin like all nommu architectures
has a 1:1 virtual to physical mapping.

Signed-off-by: Christoph Hellwig 
---
 arch/blackfin/kernel/dma-mapping.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/blackfin/kernel/dma-mapping.c 
b/arch/blackfin/kernel/dma-mapping.c
index df437e5..e2c4d1a 100644
--- a/arch/blackfin/kernel/dma-mapping.c
+++ b/arch/blackfin/kernel/dma-mapping.c
@@ -120,7 +120,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg_list, 
int nents,
int i;
 
for_each_sg(sg_list, sg, nents, i) {
-   sg->dma_address = (dma_addr_t) sg_virt(sg);
+   sg->dma_address = sg_phys(sg);
__dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
}
 
@@ -135,7 +135,7 @@ void dma_sync_sg_for_device(struct device *dev, struct 
scatterlist *sg_list,
int i;
 
for_each_sg(sg_list, sg, nelems, i) {
-   sg->dma_address = (dma_addr_t) sg_virt(sg);
+   sg->dma_address = sg_phys(sg);
__dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
}
 }
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 22/31] metag: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page().

Signed-off-by: Christoph Hellwig 
---
 arch/metag/include/asm/dma-mapping.h | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/metag/include/asm/dma-mapping.h 
b/arch/metag/include/asm/dma-mapping.h
index eb5cdec..2ae9057 100644
--- a/arch/metag/include/asm/dma-mapping.h
+++ b/arch/metag/include/asm/dma-mapping.h
@@ -55,10 +55,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sglist, 
int nents,
WARN_ON(nents == 0 || sglist[0].length == 0);
 
for_each_sg(sglist, sg, nents, i) {
-   BUG_ON(!sg_page(sg));
-
sg->dma_address = sg_phys(sg);
-   dma_sync_for_device(sg_virt(sg), sg->length, direction);
+   if (sg_has_page(sg))
+   dma_sync_for_device(sg_virt(sg), sg->length, direction);
}
 
return nents;
@@ -94,10 +93,9 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sglist, 
int nhwentries,
WARN_ON(nhwentries == 0 || sglist[0].length == 0);
 
for_each_sg(sglist, sg, nhwentries, i) {
-   BUG_ON(!sg_page(sg));
-
sg->dma_address = sg_phys(sg);
-   dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
+   if (sg_has_page(sg))
+   dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
}
 }
 
@@ -140,8 +138,10 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist 
*sglist, int nelems,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nelems, i)
-   dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
+   for_each_sg(sglist, sg, nelems, i) {
+   if (sg_has_page(sg))
+   dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
+   }
 }
 
 static inline void
@@ -151,8 +151,10 @@ dma_sync_sg_for_device(struct device *dev, struct 
scatterlist *sglist,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nelems, i)
-   dma_sync_for_device(sg_virt(sg), sg->length, direction);
+   for_each_sg(sglist, sg, nelems, i) {
+   if (sg_has_page(sg))
+   dma_sync_for_device(sg_virt(sg), sg->length, direction);
+   }
 }
 
 static inline int
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 23/31] sh: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page().

Signed-off-by: Christoph Hellwig 
---
 arch/sh/kernel/dma-nommu.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c
index 5b0bfcd..3b64dc7 100644
--- a/arch/sh/kernel/dma-nommu.c
+++ b/arch/sh/kernel/dma-nommu.c
@@ -33,9 +33,8 @@ static int nommu_map_sg(struct device *dev, struct 
scatterlist *sg,
WARN_ON(nents == 0 || sg[0].length == 0);
 
for_each_sg(sg, s, nents, i) {
-   BUG_ON(!sg_page(s));
-
-   dma_cache_sync(dev, sg_virt(s), s->length, dir);
+   if (sg_has_page(s))
+   dma_cache_sync(dev, sg_virt(s), s->length, dir);
 
s->dma_address = sg_phys(s);
s->dma_length = s->length;
@@ -57,8 +56,10 @@ static void nommu_sync_sg(struct device *dev, struct 
scatterlist *sg,
struct scatterlist *s;
int i;
 
-   for_each_sg(sg, s, nelems, i)
-   dma_cache_sync(dev, sg_virt(s), s->length, dir);
+   for_each_sg(sg, s, nelems, i) {
+   if (sg_has_page(s))
+   dma_cache_sync(dev, sg_virt(s), s->length, dir);
+   }
 }
 #endif
 
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 24/31] xtensa: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page().

Signed-off-by: Christoph Hellwig 
---
 arch/xtensa/include/asm/dma-mapping.h | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/arch/xtensa/include/asm/dma-mapping.h 
b/arch/xtensa/include/asm/dma-mapping.h
index 1f5f6dc..262a1d1 100644
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
@@ -61,10 +61,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sglist, 
int nents,
BUG_ON(direction == DMA_NONE);
 
for_each_sg(sglist, sg, nents, i) {
-   BUG_ON(!sg_page(sg));
-
sg->dma_address = sg_phys(sg);
-   consistent_sync(sg_virt(sg), sg->length, direction);
+   if (sg_has_page(sg))
+   consistent_sync(sg_virt(sg), sg->length, direction);
}
 
return nents;
@@ -131,8 +130,10 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist 
*sglist, int nelems,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nelems, i)
-   consistent_sync(sg_virt(sg), sg->length, dir);
+   for_each_sg(sglist, sg, nelems, i) {
+   if (sg_has_page(sg))
+   consistent_sync(sg_virt(sg), sg->length, dir);
+   }
 }
 
 static inline void
@@ -142,8 +143,10 @@ dma_sync_sg_for_device(struct device *dev, struct 
scatterlist *sglist,
int i;
struct scatterlist *sg;
 
-   for_each_sg(sglist, sg, nelems, i)
-   consistent_sync(sg_virt(sg), sg->length, dir);
+   for_each_sg(sglist, sg, nelems, i) {
+   if (sg_has_page(sg))
+   consistent_sync(sg_virt(sg), sg->length, dir);
+   }
 }
 static inline int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 25/31] frv: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Only call kmap_atomic_primary when the SG entry is mapped into
kernel virtual space.

XXX: the code already looks odd due to the lack of pairing between
kmap_atomic_primary and kunmap_atomic_primary.  Does it work either
before or after this patch?

Signed-off-by: Christoph Hellwig 
---
 arch/frv/mb93090-mb00/pci-dma.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 4d1f01d..77b3a1c 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -63,6 +63,9 @@ int dma_map_sg(struct device *dev, struct scatterlist 
*sglist, int nents,
dampr2 = __get_DAMPR(2);
 
for_each_sg(sglist, sg, nents, i) {
+   if (!sg_has_page(sg))
+   continue;
+
vaddr = kmap_atomic_primary(sg_page(sg));
 
frv_dcache_writeback((unsigned long) vaddr,
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 26/31] openrisc: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page() and use
sg_phys to get the physical address directly.

Signed-off-by: Christoph Hellwig 
---
 arch/openrisc/kernel/dma.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c
index 0b77ddb..94ed052 100644
--- a/arch/openrisc/kernel/dma.c
+++ b/arch/openrisc/kernel/dma.c
@@ -184,8 +184,13 @@ or1k_map_sg(struct device *dev, struct scatterlist *sg,
int i;
 
for_each_sg(sg, s, nents, i) {
-   s->dma_address = or1k_map_page(dev, sg_page(s), s->offset,
-  s->length, dir, NULL);
+   if (sg_has_page(s)) {
+   s->dma_address = or1k_map_page(dev, sg_page(s),
+   s->offset, s->length, dir,
+   NULL);
+   } else {
+   s->dma_address = sg_phys(s);
+   }
}
 
return nents;
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 27/31] mips: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page() and use
sg_phys to get the physical address directly.  To do this consolidate
the two platform callouts using pages and virtual addresses into a
single one using a physical address.

Signed-off-by: Christoph Hellwig 
---
 arch/mips/bmips/dma.c  |  9 ++--
 arch/mips/include/asm/mach-ath25/dma-coherence.h   | 10 ++---
 arch/mips/include/asm/mach-bmips/dma-coherence.h   |  4 ++--
 .../include/asm/mach-cavium-octeon/dma-coherence.h | 11 ++
 arch/mips/include/asm/mach-generic/dma-coherence.h | 12 +++
 arch/mips/include/asm/mach-ip27/dma-coherence.h| 16 +++---
 arch/mips/include/asm/mach-ip32/dma-coherence.h| 19 +++-
 arch/mips/include/asm/mach-jazz/dma-coherence.h| 11 +++---
 .../include/asm/mach-loongson64/dma-coherence.h| 16 +++---
 arch/mips/mm/dma-default.c | 25 --
 10 files changed, 37 insertions(+), 96 deletions(-)

diff --git a/arch/mips/bmips/dma.c b/arch/mips/bmips/dma.c
index 04790f4..13fc891 100644
--- a/arch/mips/bmips/dma.c
+++ b/arch/mips/bmips/dma.c
@@ -52,14 +52,9 @@ static dma_addr_t bmips_phys_to_dma(struct device *dev, 
phys_addr_t pa)
return pa;
 }
 
-dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+dma_addr_t plat_map_dma_mem(struct device *dev, phys_addr_t phys, size_t size)
 {
-   return bmips_phys_to_dma(dev, virt_to_phys(addr));
-}
-
-dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
-{
-   return bmips_phys_to_dma(dev, page_to_phys(page));
+   return bmips_phys_to_dma(dev, phys);
 }
 
 unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h 
b/arch/mips/include/asm/mach-ath25/dma-coherence.h
index d5defdd..4330de6 100644
--- a/arch/mips/include/asm/mach-ath25/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -31,15 +31,9 @@ static inline dma_addr_t ath25_dev_offset(struct device *dev)
 }
 
 static inline dma_addr_t
-plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+plat_map_dma_mem(struct device *dev, phys_addr_t phys, size_t size)
 {
-   return virt_to_phys(addr) + ath25_dev_offset(dev);
-}
-
-static inline dma_addr_t
-plat_map_dma_mem_page(struct device *dev, struct page *page)
-{
-   return page_to_phys(page) + ath25_dev_offset(dev);
+   return phys + ath25_dev_offset(dev);
 }
 
 static inline unsigned long
diff --git a/arch/mips/include/asm/mach-bmips/dma-coherence.h 
b/arch/mips/include/asm/mach-bmips/dma-coherence.h
index d29781f..1b9a7f4 100644
--- a/arch/mips/include/asm/mach-bmips/dma-coherence.h
+++ b/arch/mips/include/asm/mach-bmips/dma-coherence.h
@@ -21,8 +21,8 @@
 
 struct device;
 
-extern dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t 
size);
-extern dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page);
+extern dma_addr_t plat_map_dma_mem(struct device *dev, phys_addr_t phys,
+   size_t size);
 extern unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr);
 
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h 
b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 460042e..d0988c7 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -19,15 +19,8 @@ struct device;
 
 extern void octeon_pci_dma_init(void);
 
-static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
-   size_t size)
-{
-   BUG();
-   return 0;
-}
-
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-   struct page *page)
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, phys_addr_t phys,
+   size_t size)
 {
BUG();
return 0;
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h 
b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 0f8a354..2dfb133 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -11,16 +11,10 @@
 
 struct device;
 
-static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
-   size_t size)
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, phys_addr_t phys,
+   size_t size)
 {
-   return virt_to_phys(addr);
-}
-
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-   struct page *page)
-{
-   return page_to_phys(page);
+   return phys;
 }
 
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h 
b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 1daa644..2578b9d 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h

[PATCH 28/31] powerpc: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page().

Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/kernel/dma.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 35e4dcc..cece40b 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -135,7 +135,10 @@ static int dma_direct_map_sg(struct device *dev, struct 
scatterlist *sgl,
for_each_sg(sgl, sg, nents, i) {
sg->dma_address = sg_phys(sg) + get_dma_offset(dev);
sg->dma_length = sg->length;
-   __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
+   if (sg_has_page(sg)) {
+   __dma_sync_page(sg_page(sg), sg->offset, sg->length,
+   direction);
+   }
}
 
return nents;
@@ -200,7 +203,10 @@ static inline void dma_direct_sync_sg(struct device *dev,
int i;
 
for_each_sg(sgl, sg, nents, i)
-   __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
+   if (sg_has_page(sg)) {
+   __dma_sync_page(sg_page(sg), sg->offset, sg->length,
+   direction);
+   }
 }
 
 static inline void dma_direct_sync_single(struct device *dev,
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 29/31] parisc: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Make all cache invalidation conditional on sg_has_page() and use
sg_phys to get the physical address directly.

Signed-off-by: Christoph Hellwig 
---
 arch/parisc/kernel/pci-dma.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index b9402c9..6cad0e0 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -483,11 +483,13 @@ static int pa11_dma_map_sg(struct device *dev, struct 
scatterlist *sglist, int n
BUG_ON(direction == DMA_NONE);
 
for_each_sg(sglist, sg, nents, i) {
-   unsigned long vaddr = (unsigned long)sg_virt(sg);
-
-   sg_dma_address(sg) = (dma_addr_t) virt_to_phys(vaddr);
+   sg_dma_address(sg) = sg_phys(sg);
sg_dma_len(sg) = sg->length;
-   flush_kernel_dcache_range(vaddr, sg->length);
+
+   if (sg_has_page(sg)) {
+   flush_kernel_dcache_range((unsigned long)sg_virt(sg),
+ sg->length);
+   }
}
return nents;
 }
@@ -504,9 +506,10 @@ static void pa11_dma_unmap_sg(struct device *dev, struct 
scatterlist *sglist, in
 
/* once we do combining we'll need to use 
phys_to_virt(sg_dma_address(sglist)) */
 
-   for_each_sg(sglist, sg, nents, i)
-   flush_kernel_vmap_range(sg_virt(sg), sg->length);
-   return;
+   for_each_sg(sglist, sg, nents, i) {
+   if (sg_has_page(sg))
+   flush_kernel_vmap_range(sg_virt(sg), sg->length);
+   }
 }
 
 static void pa11_dma_sync_single_for_cpu(struct device *dev, dma_addr_t 
dma_handle, unsigned long offset, size_t size, enum dma_data_direction 
direction)
@@ -530,8 +533,10 @@ static void pa11_dma_sync_sg_for_cpu(struct device *dev, 
struct scatterlist *sgl
 
/* once we do combining we'll need to use 
phys_to_virt(sg_dma_address(sglist)) */
 
-   for_each_sg(sglist, sg, nents, i)
-   flush_kernel_vmap_range(sg_virt(sg), sg->length);
+   for_each_sg(sglist, sg, nents, i) {
+   if (sg_has_page(sg))
+   flush_kernel_vmap_range(sg_virt(sg), sg->length);
+   }
 }
 
 static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist 
*sglist, int nents, enum dma_data_direction direction)
@@ -541,8 +546,10 @@ static void pa11_dma_sync_sg_for_device(struct device 
*dev, struct scatterlist *
 
/* once we do combining we'll need to use 
phys_to_virt(sg_dma_address(sglist)) */
 
-   for_each_sg(sglist, sg, nents, i)
-   flush_kernel_vmap_range(sg_virt(sg), sg->length);
+   for_each_sg(sglist, sg, nents, i) {
+   if (sg_has_page(sg))
+   flush_kernel_vmap_range(sg_virt(sg), sg->length);
+   }
 }
 
 struct hppa_dma_ops pcxl_dma_ops = {
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 30/31] intel-iommu: handle page-less SG entries

2015-08-12 Thread Christoph Hellwig
Just remove a BUG_ON, the code handles them just fine as-is.

Signed-off-by: Christoph Hellwig 
---
 drivers/iommu/intel-iommu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 3541d65..ae10573 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3622,7 +3622,6 @@ static int intel_nontranslate_map_sg(struct device *hddev,
struct scatterlist *sg;
 
for_each_sg(sglist, sg, nelems, i) {
-   BUG_ON(!sg_page(sg));
sg->dma_address = sg_phys(sg);
sg->dma_length = sg->length;
}
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 31/31] dma-mapping-common: skip kmemleak checks for page-less SG entries

2015-08-12 Thread Christoph Hellwig
Signed-off-by: Christoph Hellwig 
---
 include/asm-generic/dma-mapping-common.h | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/asm-generic/dma-mapping-common.h 
b/include/asm-generic/dma-mapping-common.h
index 940d5ec..afc3eaf 100644
--- a/include/asm-generic/dma-mapping-common.h
+++ b/include/asm-generic/dma-mapping-common.h
@@ -51,8 +51,10 @@ static inline int dma_map_sg_attrs(struct device *dev, 
struct scatterlist *sg,
int i, ents;
struct scatterlist *s;
 
-   for_each_sg(sg, s, nents, i)
-   kmemcheck_mark_initialized(sg_virt(s), s->length);
+   for_each_sg(sg, s, nents, i) {
+   if (sg_has_page(s))
+   kmemcheck_mark_initialized(sg_virt(s), s->length);
+   }
BUG_ON(!valid_dma_direction(dir));
ents = ops->map_sg(dev, sg, nents, dir, attrs);
BUG_ON(ents < 0);
-- 
1.9.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: RFC: prepare for struct scatterlist entries without page backing

2015-08-13 Thread Christoph Hellwig
On Wed, Aug 12, 2015 at 03:42:47PM +0300, Boaz Harrosh wrote:
> The support I have suggested and submitted for zone-less sections.
> (In my add_persistent_memory() patchset)
>
> Would work perfectly well and transparent for all such multimedia cases.
> (All hacks removed). In fact I have loaded pmem (with-pages) on a VRAM
> a few times and it is great easy fun. (I wanted to experiment with cached
> memory over a pcie)

And everyone agree that it was both buggy and incomplete.

Dan has done a respin of the page backed nvdimm work with most of
these comments addressed.

I have to say I hate both pfn-based I/O [1] and page backed nvdimms with
passion, so we're looking into the lesser evil with an open mind.

[1] not the SGL part posted here, which I think is quite sane.  The bio
side is much worse, though.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 29/31] parisc: handle page-less SG entries

2015-08-13 Thread Christoph Hellwig
On Wed, Aug 12, 2015 at 09:01:02AM -0700, Linus Torvalds wrote:
> I'm assuming that anybody who wants to use the page-less
> scatter-gather lists always does so on memory that isn't actually
> virtually mapped at all, or only does so on sane architectures that
> are cache coherent at a physical level, but I'd like that assumption
> *documented* somewhere.

It's temporarily mapped by kmap-like helpers.  That code isn't in
this series. The most recent version of it is here:

https://git.kernel.org/cgit/linux/kernel/git/djbw/nvdimm.git/commit/?h=pfn&id=de8237c99fdb4352be2193f3a7610e902b9bb2f0

note that it's not doing the cache flushing it would have to do yet, but
it's also only enabled for x86 at the moment.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 31/31] dma-mapping-common: skip kmemleak checks for page-less SG entries

2015-08-13 Thread Christoph Hellwig
On Wed, Aug 12, 2015 at 09:05:15AM -0700, Linus Torvalds wrote:
> [ Again, I'm responding to one random patch - this pattern was in
> other patches too.  ]
> 
> A question: do we actually expect to mix page-less and pageful SG
> entries in the same SG list?
> 
> How does that happen?

Both for DAX and the video buffer case people could do direct I/O
spanning the boundary between such a VMA and a normal one unless
we add special code to prevent that.  Right now I don't think it's
all that useful, but then again it doesn't seem harmful either
and adding those checks might add up.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: RFC: prepare for struct scatterlist entries without page backing

2015-08-13 Thread Christoph Hellwig
On Thu, Aug 13, 2015 at 09:37:37AM +1000, Julian Calaby wrote:
> I.e. ~90% of this patch set seems to be just mechanically dropping
> BUG_ON()s and converting open coded stuff to use accessor functions
> (which should be macros or get inlined, right?) - and the remaining
> bit is not flushing if we don't have a physical page somewhere.

Which is was 90%.  By lines changed most actually is the diffs for
the cache flushing.

> Would it make sense to split this patch set into a few bits: one to
> drop all the useless BUG_ON()s, one to convert all the open coded
> stuff to accessor functions, then another to do the actual page-less
> sg stuff?

Without the ifs the BUG_ON() actually are useful to assert we
never feed the sort of physical addresses we can't otherwise support,
so I don't think that part is doable.

A simple series to make more use of sg_phys and add sg_pfn might
still be useful, though.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 4/5] dma-mapping: consolidate dma_supported

2015-08-13 Thread Christoph Hellwig
Most architectures just call into ->dma_supported, but some also return 1
if the method is not present, or 0 if no dma ops are present (although
that should never happeb). Consolidate this more broad version into
common code.

Also fix h8300 which inorrectly always returned 0, which would have been
a problem if it's dma_set_mask implementation wasn't a similarly buggy
noop.

As a few architectures have much more elaborate implementations, we
still allow for arch overrides.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  5 -
 arch/arm/include/asm/dma-mapping.h|  5 +++--
 arch/arm64/include/asm/dma-mapping.h  |  6 --
 arch/h8300/include/asm/dma-mapping.h  |  5 -
 arch/hexagon/include/asm/dma-mapping.h|  1 +
 arch/ia64/include/asm/dma-mapping.h   |  6 --
 arch/microblaze/include/asm/dma-mapping.h | 11 ---
 arch/mips/include/asm/dma-mapping.h   |  6 --
 arch/openrisc/include/asm/dma-mapping.h   |  5 +++--
 arch/powerpc/include/asm/dma-mapping.h| 11 ---
 arch/s390/include/asm/dma-mapping.h   |  9 -
 arch/sh/include/asm/dma-mapping.h | 10 --
 arch/sparc/include/asm/dma-mapping.h  |  1 +
 arch/tile/include/asm/dma-mapping.h   |  6 --
 arch/unicore32/include/asm/dma-mapping.h  | 10 --
 arch/x86/include/asm/dma-mapping.h|  4 +++-
 include/asm-generic/dma-mapping-common.h  | 13 +
 17 files changed, 24 insertions(+), 90 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 80ac3e8..9d763e5 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,11 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   return get_dma_ops(dev)->dma_supported(dev, mask);
-}
-
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
return get_dma_ops(dev)->set_dma_mask(dev, mask);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 2fa33d7..b90d247 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -38,6 +38,9 @@ static inline void set_dma_ops(struct device *dev, struct 
dma_map_ops *ops)
dev->archdata.dma_ops = ops;
 }
 
+#define HAVE_ARCH_DMA_SUPPORTED 1
+extern int dma_supported(struct device *dev, u64 mask);
+
 #include 
 
 static inline int dma_set_mask(struct device *dev, u64 mask)
@@ -166,8 +169,6 @@ static inline bool dma_capable(struct device *dev, 
dma_addr_t addr, size_t size)
 
 static inline void dma_mark_clean(void *addr, size_t size) { }
 
-extern int dma_supported(struct device *dev, u64 mask);
-
 extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
 
 /**
diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index f45f444..f519a58 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -84,12 +84,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, 
dma_addr_t dev_addr)
return (phys_addr_t)dev_addr;
 }
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   struct dma_map_ops *ops = get_dma_ops(dev);
-   return ops->dma_supported(dev, mask);
-}
-
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
if (!dev->dma_mask || !dma_supported(dev, mask))
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
index 5eef053..48d652e 100644
--- a/arch/h8300/include/asm/dma-mapping.h
+++ b/arch/h8300/include/asm/dma-mapping.h
@@ -10,11 +10,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   return 0;
-}
-
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
return 0;
diff --git a/arch/hexagon/include/asm/dma-mapping.h 
b/arch/hexagon/include/asm/dma-mapping.h
index e661192..36e8de7 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -43,6 +43,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
return dma_ops;
 }
 
+#define HAVE_ARCH_DMA_SUPPORTED 1
 extern int dma_supported(struct device *dev, u64 mask);
 extern int dma_set_mask(struct device *dev, u64 mask);
 extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
diff --git a/arch/ia64/include/asm/dma-mapping.h 
b/arch/ia64/include/asm/dma-mapping.h
index 27b713d..7982caa 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -27,12 +27,6 @@ extern void machvec_dma_sync_sg(struct device *, struct 
scatterlist *, int,
 
 #include 
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   struct dma_map_ops *op

provide more common DMA API functions

2015-08-13 Thread Christoph Hellwig
Since 2009 we have a nice asm-generic header implementing lots of DMA API
functions for architectures using struct dma_map_ops, but unfortunately
it's still missing a lot of APIs that all architectures still have to
duplicate.

This series consolidates the remaining functions, although we still
need arch opt outs for two of them as a few architectures have very
non-standard implementations.

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 1/5] dma-mapping: consolidate dma_{alloc, free}_{attrs, coherent}

2015-08-13 Thread Christoph Hellwig
The coherent DMA allocator works the same over all architectures supporting
dma_map operations.

This patch consolidates them and converges the minor differences:

 - the debug_dma helpers are now called from all architectures, including
   those that were previously missing them
 - dma_alloc_from_coherent and dma_release_from_coherent are now always
   called from the generic alloc/free routines instead of the ops
   dma-mapping-common.h always includes dma-coherent.h to get the defintions
   for them, or the stubs if the architecture doesn't support this feature
 - checks for ->alloc / ->free presence are removed.  There is only one
   magic instead of dma_map_ops without them (mic_dma_ops) and that one
   is x86 only anyway.

Besides that only x86 needs special treatment to replace a default devices
if none is passed and tweak the gfp_flags.  An optional arch hook is provided
for that.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  | 18 --
 arch/arm/include/asm/dma-mapping.h| 29 
 arch/arm/mm/dma-mapping.c | 11 --
 arch/arm64/include/asm/dma-mapping.h  | 33 --
 arch/h8300/include/asm/dma-mapping.h  | 26 --
 arch/hexagon/include/asm/dma-mapping.h| 33 --
 arch/ia64/include/asm/dma-mapping.h   | 25 -
 arch/microblaze/include/asm/dma-mapping.h | 31 -
 arch/mips/cavium-octeon/dma-octeon.c  |  8 -
 arch/mips/include/asm/dma-mapping.h   | 31 -
 arch/mips/loongson64/common/dma-swiotlb.c |  8 -
 arch/mips/mm/dma-default.c|  7 
 arch/mips/netlogic/common/nlm-dma.c   |  8 -
 arch/openrisc/include/asm/dma-mapping.h   | 30 
 arch/powerpc/include/asm/dma-mapping.h| 33 --
 arch/s390/include/asm/dma-mapping.h   | 31 -
 arch/sh/include/asm/dma-mapping.h | 37 
 arch/sparc/include/asm/dma-mapping.h  | 26 --
 arch/tile/include/asm/dma-mapping.h   | 27 --
 arch/unicore32/include/asm/dma-mapping.h  | 24 -
 arch/x86/include/asm/dma-mapping.h| 16 ++---
 arch/x86/kernel/pci-dma.c | 49 +-
 drivers/xen/swiotlb-xen.c |  6 
 include/asm-generic/dma-mapping-common.h  | 58 +++
 24 files changed, 70 insertions(+), 535 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index dfa32f0..9fef5bd 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,24 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-#define dma_alloc_coherent(d,s,h,f)dma_alloc_attrs(d,s,h,f,NULL)
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-   dma_addr_t *dma_handle, gfp_t gfp,
-   struct dma_attrs *attrs)
-{
-   return get_dma_ops(dev)->alloc(dev, size, dma_handle, gfp, attrs);
-}
-
-#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
-
-static inline void dma_free_attrs(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
-{
-   get_dma_ops(dev)->free(dev, size, vaddr, dma_handle, attrs);
-}
-
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
return get_dma_ops(dev)->mapping_error(dev, dma_addr);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index b52101d..2ae3424 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -8,7 +8,6 @@
 #include 
 #include 
 
-#include 
 #include 
 
 #include 
@@ -209,21 +208,6 @@ extern int arm_dma_set_mask(struct device *dev, u64 
dma_mask);
 extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
   gfp_t gfp, struct dma_attrs *attrs);
 
-#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-  dma_addr_t *dma_handle, gfp_t flag,
-  struct dma_attrs *attrs)
-{
-   struct dma_map_ops *ops = get_dma_ops(dev);
-   void *cpu_addr;
-   BUG_ON(!ops);
-
-   cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
-   debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
-   return cpu_addr;
-}
-
 /**
  * arm_dma_free - free memory allocated by arm_dma_alloc
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -241,19 +225,6 @@ static inline void *dma_alloc_attrs(struct device *dev, 
size_t size,
 extern void arm_dma_free(struct d

[PATCH 2/5] dma-mapping: consolidate dma_{alloc,free}_noncoherent

2015-08-13 Thread Christoph Hellwig
Most architectures do not support non-coherent allocations and either
define dma_{alloc,free}_noncoherent to their coherent versions or stub
them out.

Openrisc uses dma_{alloc,free}_attrs to implement them, and only Mips
implements them directly.

This patch moves the Openrisc version to common code, and handles the
DMA_ATTR_NON_CONSISTENT case in the mips dma_map_ops instance.

Note that actual non-coherent allocations require a dma_cache_sync
implementation, so if non-coherent allocations didn't work on
an architecture before this patch they still won't work after it.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  3 ---
 arch/arm/include/asm/dma-mapping.h| 15 ---
 arch/arm64/include/asm/dma-mapping.h  | 14 --
 arch/h8300/include/asm/dma-mapping.h  |  3 ---
 arch/hexagon/include/asm/dma-mapping.h|  3 ---
 arch/ia64/include/asm/dma-mapping.h   |  3 ---
 arch/microblaze/include/asm/dma-mapping.h |  3 ---
 arch/mips/include/asm/dma-mapping.h   |  6 --
 arch/mips/mm/dma-default.c| 20 +++-
 arch/openrisc/include/asm/dma-mapping.h   | 20 
 arch/powerpc/include/asm/dma-mapping.h|  3 ---
 arch/s390/include/asm/dma-mapping.h   |  3 ---
 arch/sh/include/asm/dma-mapping.h |  3 ---
 arch/sparc/include/asm/dma-mapping.h  |  3 ---
 arch/tile/include/asm/dma-mapping.h   |  3 ---
 arch/unicore32/include/asm/dma-mapping.h  |  3 ---
 arch/x86/include/asm/dma-mapping.h|  3 ---
 include/asm-generic/dma-mapping-common.h  | 18 ++
 18 files changed, 33 insertions(+), 96 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 9fef5bd..0552bf0 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -27,9 +27,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return get_dma_ops(dev)->set_dma_mask(dev, mask);
 }
 
-#define dma_alloc_noncoherent(d, s, h, f)  dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h)   dma_free_coherent(d, s, v, h)
-
 #define dma_cache_sync(dev, va, size, dir)   ((void)0)
 
 #endif /* _ALPHA_DMA_MAPPING_H */
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 2ae3424..ab521d5 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -175,21 +175,6 @@ static inline int dma_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
return dma_addr == DMA_ERROR_CODE;
 }
 
-/*
- * Dummy noncoherent implementation.  We don't provide a dma_cache_sync
- * function so drivers using this API are highlighted with build warnings.
- */
-static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
-   dma_addr_t *handle, gfp_t gfp)
-{
-   return NULL;
-}
-
-static inline void dma_free_noncoherent(struct device *dev, size_t size,
-   void *cpu_addr, dma_addr_t handle)
-{
-}
-
 extern int dma_supported(struct device *dev, u64 mask);
 
 extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index 5e11b3f..178e60b 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -118,19 +118,5 @@ static inline void dma_mark_clean(void *addr, size_t size)
 {
 }
 
-/*
- * There is no dma_cache_sync() implementation, so just return NULL here.
- */
-static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t flags)
-{
-   return NULL;
-}
-
-static inline void dma_free_noncoherent(struct device *dev, size_t size,
-   void *cpu_addr, dma_addr_t handle)
-{
-}
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_DMA_MAPPING_H */
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
index 826aa9b..72465ce 100644
--- a/arch/h8300/include/asm/dma-mapping.h
+++ b/arch/h8300/include/asm/dma-mapping.h
@@ -20,9 +20,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return 0;
 }
 
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
return 0;
diff --git a/arch/hexagon/include/asm/dma-mapping.h 
b/arch/hexagon/include/asm/dma-mapping.h
index c20d3ca..58d2d8f 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -34,9 +34,6 @@ extern int bad_dma_address;
 
 extern struct dma_map_ops *dma_ops;
 
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h

[PATCH 3/5] dma-mapping: cosolidate dma_mapping_error

2015-08-13 Thread Christoph Hellwig
Currently there are three valid implementations of dma_mapping_error:

 (1) call ->mapping_error
 (2) check for a hardcoded error code
 (3) always return 0

This patch provides a common implementation that calls ->mapping_error
if present, then checks for DMA_ERROR_CODE if defined or otherwise
returns 0.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  5 -
 arch/arm/include/asm/dma-mapping.h|  9 -
 arch/arm64/include/asm/dma-mapping.h  |  7 ---
 arch/h8300/include/asm/dma-mapping.h  |  5 -
 arch/hexagon/include/asm/dma-mapping.h| 11 +--
 arch/ia64/include/asm/dma-mapping.h   |  7 ---
 arch/microblaze/include/asm/dma-mapping.h | 11 ---
 arch/mips/include/asm/dma-mapping.h   |  8 
 arch/openrisc/include/asm/dma-mapping.h   |  5 -
 arch/powerpc/include/asm/dma-mapping.h| 17 ++---
 arch/s390/include/asm/dma-mapping.h   | 10 --
 arch/sh/include/asm/dma-mapping.h | 13 ++---
 arch/sparc/include/asm/dma-mapping.h  |  6 --
 arch/tile/include/asm/dma-mapping.h   |  7 ---
 arch/unicore32/include/asm/dma-mapping.h  | 10 --
 arch/x86/include/asm/dma-mapping.h| 11 ---
 include/asm-generic/dma-mapping-common.h  | 14 ++
 17 files changed, 19 insertions(+), 137 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 0552bf0..80ac3e8 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,11 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return get_dma_ops(dev)->mapping_error(dev, dma_addr);
-}
-
 static inline int dma_supported(struct device *dev, u64 mask)
 {
return get_dma_ops(dev)->dma_supported(dev, mask);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index ab521d5..2fa33d7 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -166,15 +166,6 @@ static inline bool dma_capable(struct device *dev, 
dma_addr_t addr, size_t size)
 
 static inline void dma_mark_clean(void *addr, size_t size) { }
 
-/*
- * DMA errors are defined by all-bits-set in the DMA address.
- */
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   debug_dma_mapping_error(dev, dma_addr);
-   return dma_addr == DMA_ERROR_CODE;
-}
-
 extern int dma_supported(struct device *dev, u64 mask);
 
 extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index 178e60b..f45f444 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -84,13 +84,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, 
dma_addr_t dev_addr)
return (phys_addr_t)dev_addr;
 }
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dev_addr)
-{
-   struct dma_map_ops *ops = get_dma_ops(dev);
-   debug_dma_mapping_error(dev, dev_addr);
-   return ops->mapping_error(dev, dev_addr);
-}
-
 static inline int dma_supported(struct device *dev, u64 mask)
 {
struct dma_map_ops *ops = get_dma_ops(dev);
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
index 72465ce..5eef053 100644
--- a/arch/h8300/include/asm/dma-mapping.h
+++ b/arch/h8300/include/asm/dma-mapping.h
@@ -20,9 +20,4 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return 0;
 }
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return 0;
-}
-
 #endif
diff --git a/arch/hexagon/include/asm/dma-mapping.h 
b/arch/hexagon/include/asm/dma-mapping.h
index 58d2d8f..e661192 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -31,6 +31,7 @@
 
 struct device;
 extern int bad_dma_address;
+#define DMA_ERROR_CODE bad_dma_address
 
 extern struct dma_map_ops *dma_ops;
 
@@ -57,14 +58,4 @@ static inline bool dma_capable(struct device *dev, 
dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
 }
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
-   if (dma_ops->mapping_error)
-   return dma_ops->mapping_error(dev, dma_addr);
-
-   return (dma_addr == bad_dma_address);
-}
-
 #endif
diff --git a/arch/ia64/include/asm/dma-mapping.h 
b/arch/ia64/include/asm/dma-mapping.h
index a925ff0..27b713d 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -27,13 +27,6 @@ extern void machvec_dma_sync_sg(struct device *, struct 
scatterlist *, int,
 
 #include 
 
-static i

[PATCH 5/5] dma-mapping: consolidate dma_set_mask

2015-08-13 Thread Christoph Hellwig
Almost everyone implements dma_set_mask the same way, although some time
that's hidden in ->set_dma_mask methods.

Move this implementation to common code, including a callout to override
the post-check action, and remove duplicate instaces in methods as well.

Unfortunately some architectures overload unrelated semantics like changing
the dma_ops into it so we still need to allow for an architecture override
for now.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  5 -
 arch/alpha/kernel/pci-noop.c  | 10 --
 arch/alpha/kernel/pci_iommu.c | 11 ---
 arch/arm/common/dmabounce.c   |  9 -
 arch/arm/include/asm/dma-mapping.h|  5 -
 arch/arm/mm/dma-mapping.c | 16 
 arch/arm/xen/mm.c |  1 -
 arch/arm64/include/asm/dma-mapping.h  |  9 -
 arch/h8300/include/asm/dma-mapping.h  |  5 -
 arch/hexagon/include/asm/dma-mapping.h|  1 -
 arch/hexagon/kernel/dma.c | 11 ---
 arch/ia64/include/asm/dma-mapping.h   |  9 -
 arch/microblaze/include/asm/dma-mapping.h | 14 --
 arch/mips/include/asm/dma-mapping.h   | 16 
 arch/openrisc/include/asm/dma-mapping.h   |  9 -
 arch/powerpc/include/asm/dma-mapping.h|  4 +++-
 arch/powerpc/platforms/cell/iommu.c   |  3 ---
 arch/s390/include/asm/dma-mapping.h   |  2 --
 arch/s390/pci/pci_dma.c   | 10 --
 arch/sh/include/asm/dma-mapping.h | 14 --
 arch/sparc/include/asm/dma-mapping.h  |  5 +++--
 arch/tile/include/asm/dma-mapping.h   |  5 +++--
 arch/unicore32/include/asm/dma-mapping.h  | 10 --
 arch/x86/include/asm/dma-mapping.h|  2 --
 arch/x86/kernel/pci-dma.c | 11 ---
 drivers/xen/swiotlb-xen.c | 12 
 include/asm-generic/dma-mapping-common.h  | 16 
 include/xen/swiotlb-xen.h |  2 --
 28 files changed, 25 insertions(+), 202 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 9d763e5..72a8ca7 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,11 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_set_mask(struct device *dev, u64 mask)
-{
-   return get_dma_ops(dev)->set_dma_mask(dev, mask);
-}
-
 #define dma_cache_sync(dev, va, size, dir)   ((void)0)
 
 #endif /* _ALPHA_DMA_MAPPING_H */
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index df24b76..2b1f4a1 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -166,15 +166,6 @@ static int alpha_noop_supported(struct device *dev, u64 
mask)
return mask < 0x00ffUL ? 0 : 1;
 }
 
-static int alpha_noop_set_mask(struct device *dev, u64 mask)
-{
-   if (!dev->dma_mask || !dma_supported(dev, mask))
-   return -EIO;
-
-   *dev->dma_mask = mask;
-   return 0;
-}
-
 struct dma_map_ops alpha_noop_ops = {
.alloc  = alpha_noop_alloc_coherent,
.free   = alpha_noop_free_coherent,
@@ -182,7 +173,6 @@ struct dma_map_ops alpha_noop_ops = {
.map_sg = alpha_noop_map_sg,
.mapping_error  = alpha_noop_mapping_error,
.dma_supported  = alpha_noop_supported,
-   .set_dma_mask   = alpha_noop_set_mask,
 };
 
 struct dma_map_ops *dma_ops = &alpha_noop_ops;
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index eddee77..8969bf2 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -939,16 +939,6 @@ static int alpha_pci_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
return dma_addr == 0;
 }
 
-static int alpha_pci_set_mask(struct device *dev, u64 mask)
-{
-   if (!dev->dma_mask ||
-   !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
-   return -EIO;
-
-   *dev->dma_mask = mask;
-   return 0;
-}
-
 struct dma_map_ops alpha_pci_ops = {
.alloc  = alpha_pci_alloc_coherent,
.free   = alpha_pci_free_coherent,
@@ -958,7 +948,6 @@ struct dma_map_ops alpha_pci_ops = {
.unmap_sg   = alpha_pci_unmap_sg,
.mapping_error  = alpha_pci_mapping_error,
.dma_supported  = alpha_pci_supported,
-   .set_dma_mask   = alpha_pci_set_mask,
 };
 
 struct dma_map_ops *dma_ops = &alpha_pci_ops;
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 1143c4d..260f52a 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -440,14 +440,6 @@ static void dmabounce_sync_for_device(struct device *dev,

Re: [PATCH 2/5] dma-mapping: consolidate dma_{alloc,free}_noncoherent

2015-08-13 Thread Christoph Hellwig
On Thu, Aug 13, 2015 at 04:20:40PM +0100, Russell King - ARM Linux wrote:
> > -/*
> > - * Dummy noncoherent implementation.  We don't provide a dma_cache_sync
> > - * function so drivers using this API are highlighted with build warnings.
> > - */
> 
> I'd like a similar comment to remain after this patch explaining that we
> don't support non-coherent allocations and that it'll be highlighted by
> the lack of dma_cache_sync, otherwise I'm sure we'll start to get patches
> to add the thing.

I'll keep a modified version of this comment in the ARM dma-mapping.h
in addition to an explanation near the new common dma_alloc_noncoherent
definition, thanks!

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 5/5] dma-mapping: consolidate dma_set_mask

2015-08-13 Thread Christoph Hellwig
On Thu, Aug 13, 2015 at 04:25:05PM +0100, Russell King - ARM Linux wrote:
> On Thu, Aug 13, 2015 at 05:04:08PM +0200, Christoph Hellwig wrote:
> > diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
> > index 1143c4d..260f52a 100644
> > --- a/arch/arm/common/dmabounce.c
> > +++ b/arch/arm/common/dmabounce.c
> > @@ -440,14 +440,6 @@ static void dmabounce_sync_for_device(struct device 
> > *dev,
> > arm_dma_ops.sync_single_for_device(dev, handle, size, dir);
> >  }
> >  
> > -static int dmabounce_set_mask(struct device *dev, u64 dma_mask)
> > -{
> > -   if (dev->archdata.dmabounce)
> > -   return 0;
> > -
> > -   return arm_dma_ops.set_dma_mask(dev, dma_mask);
> 
> Are you sure about this?  A user of dmabounce gets to request any mask
> with the original code (even though it was never written back... which
> is a separate bug.)  After this, it seems that this will get limited
> by the dma_supported() check.  As this old code is about bouncing any
> buffer into DMA-able memory, it doesn't care about the DMA mask.

I think you're right.  With the default dma_supported implementation
it would be fine, but ARM uses a custom one.  I'll keep the arm
specific dma_set_mask implementation for the next round.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH v2 7/7] pmem, dax: have direct_access use __pmem annotation

2015-08-15 Thread Christoph Hellwig
On Fri, Aug 14, 2015 at 09:58:16AM -0700, Dan Williams wrote:
> > I'll merge with your code for v3.
> 
> Sounds, let me go rebase the __pfn_t patches on -mm so we'all lined up
> and collision free.

I'm doubt that we'll have PFN mapping ready for 4.3.  I'd rather see
Ross series goes first, and move the patch to remove the size argument
from ->direct access [1] over to this series as well.

[1] 
https://git.kernel.org/cgit/linux/kernel/git/djbw/nvdimm.git/commit/?h=pfn&id=8e15e69fb9e61ac563c5a7ffd9dd9a7b545cced3
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH v2 7/7] pmem, dax: have direct_access use __pmem annotation

2015-08-15 Thread Christoph Hellwig
On Thu, Aug 13, 2015 at 10:51:11AM -0600, Ross Zwisler wrote:
> Update the annotation for the kaddr pointer returned by direct_access()
> so that it is a __pmem pointer.  This is consistent with the PMEM driver
> and with how this direct_access() pointer is used in the DAX code.

IFF we stick to the __pmem annotations this looks good.

That beeing said I start to really dislike them.  We don't special
accesors to read/write from pmem, we just need to explicitly commit
it if we want to make it persistent.  So I really don't see the need
to treat it special and require all the force casts to and from the
attribute.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH v2 7/7] pmem, dax: have direct_access use __pmem annotation

2015-08-15 Thread Christoph Hellwig
On Sat, Aug 15, 2015 at 08:44:27AM -0700, Dan Williams wrote:
> That said, while we don't need special accessors we do need guarantees
> that anything that has written to a persistent memory address has done
> so in a way that wmb_pmem() is able to flush it.  It's more of a "I've
> audited this code path for wmb_pmem() compatibility so use this api to
> write to pmem."

I'm more worried about things where don't just do plain loads and stores
to a pmem region but DMA, which will end up as a nightmare of casts.

But we can wait and see how that evolves in the end..
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

provide more common DMA API functions V2

2015-08-17 Thread Christoph Hellwig
Since 2009 we have a nice asm-generic header implementing lots of DMA API
functions for architectures using struct dma_map_ops, but unfortunately
it's still missing a lot of APIs that all architectures still have to
duplicate.

This series consolidates the remaining functions, although we still
need arch opt outs for two of them as a few architectures have very
non-standard implementations.

Changes since V1:
 - keep a modified comment about dma_alloc_noncoherent vs
   dma_cache_sync in the ARM asm/dma-mapping.h
 - keep the ARM dma_set_mask instances to deal with dmabounce

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH 3/5] dma-mapping: cosolidate dma_mapping_error

2015-08-17 Thread Christoph Hellwig
Currently there are three valid implementations of dma_mapping_error:

 (1) call ->mapping_error
 (2) check for a hardcoded error code
 (3) always return 0

This patch provides a common implementation that calls ->mapping_error
if present, then checks for DMA_ERROR_CODE if defined or otherwise
returns 0.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  5 -
 arch/arm/include/asm/dma-mapping.h|  9 -
 arch/arm64/include/asm/dma-mapping.h  |  7 ---
 arch/h8300/include/asm/dma-mapping.h  |  5 -
 arch/hexagon/include/asm/dma-mapping.h| 11 +--
 arch/ia64/include/asm/dma-mapping.h   |  7 ---
 arch/microblaze/include/asm/dma-mapping.h | 11 ---
 arch/mips/include/asm/dma-mapping.h   |  8 
 arch/openrisc/include/asm/dma-mapping.h   |  5 -
 arch/powerpc/include/asm/dma-mapping.h| 17 ++---
 arch/s390/include/asm/dma-mapping.h   | 10 --
 arch/sh/include/asm/dma-mapping.h | 13 ++---
 arch/sparc/include/asm/dma-mapping.h  |  6 --
 arch/tile/include/asm/dma-mapping.h   |  7 ---
 arch/unicore32/include/asm/dma-mapping.h  | 10 --
 arch/x86/include/asm/dma-mapping.h| 11 ---
 include/asm-generic/dma-mapping-common.h  | 14 ++
 17 files changed, 19 insertions(+), 137 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 0552bf0..80ac3e8 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,11 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return get_dma_ops(dev)->mapping_error(dev, dma_addr);
-}
-
 static inline int dma_supported(struct device *dev, u64 mask)
 {
return get_dma_ops(dev)->dma_supported(dev, mask);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 2191f9c..b4f1b6b 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -172,15 +172,6 @@ static inline bool dma_capable(struct device *dev, 
dma_addr_t addr, size_t size)
 
 static inline void dma_mark_clean(void *addr, size_t size) { }
 
-/*
- * DMA errors are defined by all-bits-set in the DMA address.
- */
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   debug_dma_mapping_error(dev, dma_addr);
-   return dma_addr == DMA_ERROR_CODE;
-}
-
 extern int dma_supported(struct device *dev, u64 mask);
 
 extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index 178e60b..f45f444 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -84,13 +84,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, 
dma_addr_t dev_addr)
return (phys_addr_t)dev_addr;
 }
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dev_addr)
-{
-   struct dma_map_ops *ops = get_dma_ops(dev);
-   debug_dma_mapping_error(dev, dev_addr);
-   return ops->mapping_error(dev, dev_addr);
-}
-
 static inline int dma_supported(struct device *dev, u64 mask)
 {
struct dma_map_ops *ops = get_dma_ops(dev);
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
index 72465ce..5eef053 100644
--- a/arch/h8300/include/asm/dma-mapping.h
+++ b/arch/h8300/include/asm/dma-mapping.h
@@ -20,9 +20,4 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return 0;
 }
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return 0;
-}
-
 #endif
diff --git a/arch/hexagon/include/asm/dma-mapping.h 
b/arch/hexagon/include/asm/dma-mapping.h
index 58d2d8f..e661192 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -31,6 +31,7 @@
 
 struct device;
 extern int bad_dma_address;
+#define DMA_ERROR_CODE bad_dma_address
 
 extern struct dma_map_ops *dma_ops;
 
@@ -57,14 +58,4 @@ static inline bool dma_capable(struct device *dev, 
dma_addr_t addr, size_t size)
return addr + size - 1 <= *dev->dma_mask;
 }
 
-static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
-   if (dma_ops->mapping_error)
-   return dma_ops->mapping_error(dev, dma_addr);
-
-   return (dma_addr == bad_dma_address);
-}
-
 #endif
diff --git a/arch/ia64/include/asm/dma-mapping.h 
b/arch/ia64/include/asm/dma-mapping.h
index a925ff0..27b713d 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -27,13 +27,6 @@ extern void machvec_dma_sync_sg(struct device *, struct 
scatterlist *, int,
 
 #include 
 
-static i

[PATCH 4/5] dma-mapping: consolidate dma_supported

2015-08-17 Thread Christoph Hellwig
Most architectures just call into ->dma_supported, but some also return 1
if the method is not present, or 0 if no dma ops are present (although
that should never happeb). Consolidate this more broad version into
common code.

Also fix h8300 which inorrectly always returned 0, which would have been
a problem if it's dma_set_mask implementation wasn't a similarly buggy
noop.

As a few architectures have much more elaborate implementations, we
still allow for arch overrides.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  5 -
 arch/arm/include/asm/dma-mapping.h|  6 +++---
 arch/arm64/include/asm/dma-mapping.h  |  6 --
 arch/h8300/include/asm/dma-mapping.h  |  5 -
 arch/hexagon/include/asm/dma-mapping.h|  1 +
 arch/ia64/include/asm/dma-mapping.h   |  6 --
 arch/microblaze/include/asm/dma-mapping.h | 13 +
 arch/mips/include/asm/dma-mapping.h   |  6 --
 arch/openrisc/include/asm/dma-mapping.h   |  5 +++--
 arch/powerpc/include/asm/dma-mapping.h| 11 ---
 arch/s390/include/asm/dma-mapping.h   |  9 -
 arch/sh/include/asm/dma-mapping.h | 10 --
 arch/sparc/include/asm/dma-mapping.h  |  1 +
 arch/tile/include/asm/dma-mapping.h   |  6 --
 arch/unicore32/include/asm/dma-mapping.h  | 10 --
 arch/x86/include/asm/dma-mapping.h|  4 +++-
 include/asm-generic/dma-mapping-common.h  | 13 +
 17 files changed, 25 insertions(+), 92 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 80ac3e8..9d763e5 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,11 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   return get_dma_ops(dev)->dma_supported(dev, mask);
-}
-
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
return get_dma_ops(dev)->set_dma_mask(dev, mask);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index b4f1b6b..199b080 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -38,12 +38,14 @@ static inline void set_dma_ops(struct device *dev, struct 
dma_map_ops *ops)
dev->archdata.dma_ops = ops;
 }
 
+#define HAVE_ARCH_DMA_SUPPORTED 1
+extern int dma_supported(struct device *dev, u64 mask);
+
 /*
  * Note that while the generic code provides dummy dma_{alloc,free}_noncoherent
  * implementations, we don't provide a dma_cache_sync function so drivers using
  * this API are highlighted with build warnings. 
  */
-
 #include 
 
 static inline int dma_set_mask(struct device *dev, u64 mask)
@@ -172,8 +174,6 @@ static inline bool dma_capable(struct device *dev, 
dma_addr_t addr, size_t size)
 
 static inline void dma_mark_clean(void *addr, size_t size) { }
 
-extern int dma_supported(struct device *dev, u64 mask);
-
 extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
 
 /**
diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index f45f444..f519a58 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -84,12 +84,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, 
dma_addr_t dev_addr)
return (phys_addr_t)dev_addr;
 }
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   struct dma_map_ops *ops = get_dma_ops(dev);
-   return ops->dma_supported(dev, mask);
-}
-
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
if (!dev->dma_mask || !dma_supported(dev, mask))
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
index 5eef053..48d652e 100644
--- a/arch/h8300/include/asm/dma-mapping.h
+++ b/arch/h8300/include/asm/dma-mapping.h
@@ -10,11 +10,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-   return 0;
-}
-
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
return 0;
diff --git a/arch/hexagon/include/asm/dma-mapping.h 
b/arch/hexagon/include/asm/dma-mapping.h
index e661192..36e8de7 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -43,6 +43,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
return dma_ops;
 }
 
+#define HAVE_ARCH_DMA_SUPPORTED 1
 extern int dma_supported(struct device *dev, u64 mask);
 extern int dma_set_mask(struct device *dev, u64 mask);
 extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
diff --git a/arch/ia64/include/asm/dma-mapping.h 
b/arch/ia64/include/asm/dma-mapping.h
index 27b713d..7982caa 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/

[PATCH 5/5] dma-mapping: consolidate dma_set_mask

2015-08-17 Thread Christoph Hellwig
Almost everyone implements dma_set_mask the same way, although some time
that's hidden in ->set_dma_mask methods.

This patch consolidates those into a common implementation that either
calls ->set_dma_mask if present or otherwise uses the default
implementation.  Some architectures used to only call ->set_dma_mask
after the initial checks, and those instance have been fixed to do the
full work.  h8300 implemented dma_set_mask bogusly as a no-ops and has
been fixed.

Unfortunately some architectures overload unrelated semantics like changing
the dma_ops into it so we still need to allow for an architecture override
for now.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  5 -
 arch/alpha/kernel/pci-noop.c  | 10 --
 arch/alpha/kernel/pci_iommu.c | 11 ---
 arch/arm/include/asm/dma-mapping.h|  5 -
 arch/arm64/include/asm/dma-mapping.h  |  9 -
 arch/h8300/include/asm/dma-mapping.h  |  5 -
 arch/hexagon/include/asm/dma-mapping.h|  1 -
 arch/hexagon/kernel/dma.c | 11 ---
 arch/ia64/include/asm/dma-mapping.h   |  9 -
 arch/microblaze/include/asm/dma-mapping.h | 14 --
 arch/mips/include/asm/dma-mapping.h   | 16 
 arch/mips/loongson64/common/dma-swiotlb.c |  3 +++
 arch/openrisc/include/asm/dma-mapping.h   |  9 -
 arch/powerpc/include/asm/dma-mapping.h|  4 +++-
 arch/s390/include/asm/dma-mapping.h   |  2 --
 arch/s390/pci/pci_dma.c   | 10 --
 arch/sh/include/asm/dma-mapping.h | 14 --
 arch/sparc/include/asm/dma-mapping.h  |  4 +++-
 arch/tile/include/asm/dma-mapping.h   |  6 --
 arch/unicore32/include/asm/dma-mapping.h  | 10 --
 arch/x86/include/asm/dma-mapping.h|  2 --
 arch/x86/kernel/pci-dma.c | 11 ---
 include/asm-generic/dma-mapping-common.h  | 15 +++
 23 files changed, 28 insertions(+), 158 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 9d763e5..72a8ca7 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,11 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-static inline int dma_set_mask(struct device *dev, u64 mask)
-{
-   return get_dma_ops(dev)->set_dma_mask(dev, mask);
-}
-
 #define dma_cache_sync(dev, va, size, dir)   ((void)0)
 
 #endif /* _ALPHA_DMA_MAPPING_H */
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index df24b76..2b1f4a1 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -166,15 +166,6 @@ static int alpha_noop_supported(struct device *dev, u64 
mask)
return mask < 0x00ffUL ? 0 : 1;
 }
 
-static int alpha_noop_set_mask(struct device *dev, u64 mask)
-{
-   if (!dev->dma_mask || !dma_supported(dev, mask))
-   return -EIO;
-
-   *dev->dma_mask = mask;
-   return 0;
-}
-
 struct dma_map_ops alpha_noop_ops = {
.alloc  = alpha_noop_alloc_coherent,
.free   = alpha_noop_free_coherent,
@@ -182,7 +173,6 @@ struct dma_map_ops alpha_noop_ops = {
.map_sg = alpha_noop_map_sg,
.mapping_error  = alpha_noop_mapping_error,
.dma_supported  = alpha_noop_supported,
-   .set_dma_mask   = alpha_noop_set_mask,
 };
 
 struct dma_map_ops *dma_ops = &alpha_noop_ops;
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index eddee77..8969bf2 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -939,16 +939,6 @@ static int alpha_pci_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
return dma_addr == 0;
 }
 
-static int alpha_pci_set_mask(struct device *dev, u64 mask)
-{
-   if (!dev->dma_mask ||
-   !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
-   return -EIO;
-
-   *dev->dma_mask = mask;
-   return 0;
-}
-
 struct dma_map_ops alpha_pci_ops = {
.alloc  = alpha_pci_alloc_coherent,
.free   = alpha_pci_free_coherent,
@@ -958,7 +948,6 @@ struct dma_map_ops alpha_pci_ops = {
.unmap_sg   = alpha_pci_unmap_sg,
.mapping_error  = alpha_pci_mapping_error,
.dma_supported  = alpha_pci_supported,
-   .set_dma_mask   = alpha_pci_set_mask,
 };
 
 struct dma_map_ops *dma_ops = &alpha_pci_ops;
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 199b080..906a60e 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -48,11 +48,6 @@ extern int dma_supported(struct device *dev, u64 mask);
  */
 #include 
 
-static inline int d

[PATCH 2/5] dma-mapping: consolidate dma_{alloc,free}_noncoherent

2015-08-17 Thread Christoph Hellwig
Most architectures do not support non-coherent allocations and either
define dma_{alloc,free}_noncoherent to their coherent versions or stub
them out.

Openrisc uses dma_{alloc,free}_attrs to implement them, and only Mips
implements them directly.

This patch moves the Openrisc version to common code, and handles the
DMA_ATTR_NON_CONSISTENT case in the mips dma_map_ops instance.

Note that actual non-coherent allocations require a dma_cache_sync
implementation, so if non-coherent allocations didn't work on
an architecture before this patch they still won't work after it.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  |  3 ---
 arch/arm/include/asm/dma-mapping.h| 21 ++---
 arch/arm64/include/asm/dma-mapping.h  | 14 --
 arch/h8300/include/asm/dma-mapping.h  |  3 ---
 arch/hexagon/include/asm/dma-mapping.h|  3 ---
 arch/ia64/include/asm/dma-mapping.h   |  3 ---
 arch/microblaze/include/asm/dma-mapping.h |  3 ---
 arch/mips/include/asm/dma-mapping.h   |  6 --
 arch/mips/mm/dma-default.c| 20 +++-
 arch/openrisc/include/asm/dma-mapping.h   | 20 
 arch/powerpc/include/asm/dma-mapping.h|  3 ---
 arch/s390/include/asm/dma-mapping.h   |  3 ---
 arch/sh/include/asm/dma-mapping.h |  3 ---
 arch/sparc/include/asm/dma-mapping.h  |  3 ---
 arch/tile/include/asm/dma-mapping.h   |  3 ---
 arch/unicore32/include/asm/dma-mapping.h  |  3 ---
 arch/x86/include/asm/dma-mapping.h|  3 ---
 include/asm-generic/dma-mapping-common.h  | 18 ++
 18 files changed, 39 insertions(+), 96 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index 9fef5bd..0552bf0 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -27,9 +27,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return get_dma_ops(dev)->set_dma_mask(dev, mask);
 }
 
-#define dma_alloc_noncoherent(d, s, h, f)  dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h)   dma_free_coherent(d, s, v, h)
-
 #define dma_cache_sync(dev, va, size, dir)   ((void)0)
 
 #endif /* _ALPHA_DMA_MAPPING_H */
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index 2ae3424..2191f9c 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -38,6 +38,12 @@ static inline void set_dma_ops(struct device *dev, struct 
dma_map_ops *ops)
dev->archdata.dma_ops = ops;
 }
 
+/*
+ * Note that while the generic code provides dummy dma_{alloc,free}_noncoherent
+ * implementations, we don't provide a dma_cache_sync function so drivers using
+ * this API are highlighted with build warnings. 
+ */
+
 #include 
 
 static inline int dma_set_mask(struct device *dev, u64 mask)
@@ -175,21 +181,6 @@ static inline int dma_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
return dma_addr == DMA_ERROR_CODE;
 }
 
-/*
- * Dummy noncoherent implementation.  We don't provide a dma_cache_sync
- * function so drivers using this API are highlighted with build warnings.
- */
-static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
-   dma_addr_t *handle, gfp_t gfp)
-{
-   return NULL;
-}
-
-static inline void dma_free_noncoherent(struct device *dev, size_t size,
-   void *cpu_addr, dma_addr_t handle)
-{
-}
-
 extern int dma_supported(struct device *dev, u64 mask);
 
 extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index 5e11b3f..178e60b 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -118,19 +118,5 @@ static inline void dma_mark_clean(void *addr, size_t size)
 {
 }
 
-/*
- * There is no dma_cache_sync() implementation, so just return NULL here.
- */
-static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t flags)
-{
-   return NULL;
-}
-
-static inline void dma_free_noncoherent(struct device *dev, size_t size,
-   void *cpu_addr, dma_addr_t handle)
-{
-}
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_DMA_MAPPING_H */
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
index 826aa9b..72465ce 100644
--- a/arch/h8300/include/asm/dma-mapping.h
+++ b/arch/h8300/include/asm/dma-mapping.h
@@ -20,9 +20,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return 0;
 }
 
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
r

[PATCH 1/5] dma-mapping: consolidate dma_{alloc, free}_{attrs, coherent}

2015-08-17 Thread Christoph Hellwig
The coherent DMA allocator works the same over all architectures supporting
dma_map operations.

This patch consolidates them and converges the minor differences:

 - the debug_dma helpers are now called from all architectures, including
   those that were previously missing them
 - dma_alloc_from_coherent and dma_release_from_coherent are now always
   called from the generic alloc/free routines instead of the ops
   dma-mapping-common.h always includes dma-coherent.h to get the defintions
   for them, or the stubs if the architecture doesn't support this feature
 - checks for ->alloc / ->free presence are removed.  There is only one
   magic instead of dma_map_ops without them (mic_dma_ops) and that one
   is x86 only anyway.

Besides that only x86 needs special treatment to replace a default devices
if none is passed and tweak the gfp_flags.  An optional arch hook is provided
for that.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/include/asm/dma-mapping.h  | 18 --
 arch/arm/include/asm/dma-mapping.h| 29 
 arch/arm/mm/dma-mapping.c | 11 --
 arch/arm64/include/asm/dma-mapping.h  | 33 --
 arch/h8300/include/asm/dma-mapping.h  | 26 --
 arch/hexagon/include/asm/dma-mapping.h| 33 --
 arch/ia64/include/asm/dma-mapping.h   | 25 -
 arch/microblaze/include/asm/dma-mapping.h | 31 -
 arch/mips/cavium-octeon/dma-octeon.c  |  8 -
 arch/mips/include/asm/dma-mapping.h   | 31 -
 arch/mips/loongson64/common/dma-swiotlb.c |  8 -
 arch/mips/mm/dma-default.c|  7 
 arch/mips/netlogic/common/nlm-dma.c   |  8 -
 arch/openrisc/include/asm/dma-mapping.h   | 30 
 arch/powerpc/include/asm/dma-mapping.h| 33 --
 arch/s390/include/asm/dma-mapping.h   | 31 -
 arch/sh/include/asm/dma-mapping.h | 37 
 arch/sparc/include/asm/dma-mapping.h  | 26 --
 arch/tile/include/asm/dma-mapping.h   | 27 --
 arch/unicore32/include/asm/dma-mapping.h  | 24 -
 arch/x86/include/asm/dma-mapping.h| 16 ++---
 arch/x86/kernel/pci-dma.c | 49 +-
 drivers/xen/swiotlb-xen.c |  6 
 include/asm-generic/dma-mapping-common.h  | 58 +++
 24 files changed, 70 insertions(+), 535 deletions(-)

diff --git a/arch/alpha/include/asm/dma-mapping.h 
b/arch/alpha/include/asm/dma-mapping.h
index dfa32f0..9fef5bd 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,24 +12,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device 
*dev)
 
 #include 
 
-#define dma_alloc_coherent(d,s,h,f)dma_alloc_attrs(d,s,h,f,NULL)
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-   dma_addr_t *dma_handle, gfp_t gfp,
-   struct dma_attrs *attrs)
-{
-   return get_dma_ops(dev)->alloc(dev, size, dma_handle, gfp, attrs);
-}
-
-#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
-
-static inline void dma_free_attrs(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
-{
-   get_dma_ops(dev)->free(dev, size, vaddr, dma_handle, attrs);
-}
-
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
return get_dma_ops(dev)->mapping_error(dev, dma_addr);
diff --git a/arch/arm/include/asm/dma-mapping.h 
b/arch/arm/include/asm/dma-mapping.h
index b52101d..2ae3424 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -8,7 +8,6 @@
 #include 
 #include 
 
-#include 
 #include 
 
 #include 
@@ -209,21 +208,6 @@ extern int arm_dma_set_mask(struct device *dev, u64 
dma_mask);
 extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
   gfp_t gfp, struct dma_attrs *attrs);
 
-#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-  dma_addr_t *dma_handle, gfp_t flag,
-  struct dma_attrs *attrs)
-{
-   struct dma_map_ops *ops = get_dma_ops(dev);
-   void *cpu_addr;
-   BUG_ON(!ops);
-
-   cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
-   debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
-   return cpu_addr;
-}
-
 /**
  * arm_dma_free - free memory allocated by arm_dma_alloc
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -241,19 +225,6 @@ static inline void *dma_alloc_attrs(struct device *dev, 
size_t size,
 extern void arm_dma_free(struct d

Re: [PATCH v3 7/7] pmem, dax: have direct_access use __pmem annotation

2015-08-17 Thread Christoph Hellwig
Looks fine,

Reviewed-by: Christoph Hellwig 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: provide more common DMA API functions V2

2015-08-17 Thread Christoph Hellwig
On Mon, Aug 17, 2015 at 02:24:29PM -0700, Andrew Morton wrote:
> 110254 bytes saved, shrinking the kernel by a whopping 0.17%. 
> Thoughts?

Sounds fine to me.

> 
> I'll merge these 5 patches for 4.3.  That means I'll release them into
> linux-next after 4.2 is released.

So you only add for-4.3 code to -next after 4.2 is odd?  Isn't thast the
wrong way around?
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: provide more common DMA API functions V2

2015-08-17 Thread Christoph Hellwig
On Mon, Aug 17, 2015 at 10:45:52PM -0700, Andrew Morton wrote:
> > > 
> > > I'll merge these 5 patches for 4.3.  That means I'll release them into
> > > linux-next after 4.2 is released.
> > 
> > So you only add for-4.3 code to -next after 4.2 is odd?  Isn't thast the
> > wrong way around?
> 
> Linus will be releasing 4.2 in 1-2 weeks and until then, linux-next is
> supposed to contain only 4.2 material.  Once 4.2 is released,
> linux-next is open for 4.3 material.

Hmm, I'm pretty sure there's tons of 4.3 material in linux-next at the
moment, at least I got merge warning messages from Stephen about
some yesterday.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: provide more common DMA API functions V2

2015-08-19 Thread Christoph Hellwig
On Tue, Aug 18, 2015 at 09:51:07AM +0200, Ingo Molnar wrote:
> I.e. shouldn't this be:
> 
> > I'll merge these 5 patches for 4.4.  That means I'll release them into 
> > linux-next after 4.2 is released.
> >
> > [...]
> > 
> > Linus will be releasing 4.2 in 1-2 weeks and until then, linux-next is 
> > supposed 
> > to contain only 4.3 material.  Once 4.2 is released and the 4.3 merge 
> > window 
> > opens, linux-next is open for 4.4 material.
> 
> ?

That would make a lot more sense.  But also be said as I intended
these as the simple part of the dma work I'd like to get into 4.3.

Andrew, if you think it's not 4.3 material I'd rather keep them in
my git tree for now so that I can stack additional patches I have
in progress on top.  A non-git based tree like yours is unfortunately
very bad for patches that are dependencies for others.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH] powerpc/spufs: Initialise inode->i_ino in spufs_new_inode()

2013-04-23 Thread Christoph Hellwig
Looks good.

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [RESEND][PATCH 1/2] lib/scatterlist: Make ARCH_HAS_SG_CHAIN an actual Kconfig

2014-03-23 Thread Christoph Hellwig
On Sun, Mar 23, 2014 at 02:04:46PM +1100, Benjamin Herrenschmidt wrote:
> 
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 1594945..8122294 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -82,6 +82,7 @@ config ARM
> >   .
> >  
> >  config ARM_HAS_SG_CHAIN
> > +   select ARCH_HAS_SG_CHAIN
> > bool
> >  
> 
> Heh, a self-selecting config option... I didn't know that trick !

ARM vs ARCH.  However the arm variant of the variable should probably be
consolidated into the ARCH one as a follow up.

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 2/2] MAINTAINERS: ibmvfc driver maintainer change

2015-01-18 Thread Christoph Hellwig
Brian, can you ACK this one?

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH] powerpc/configs: Re-enable CONFIG_SCSI_DH

2015-09-30 Thread Christoph Hellwig
On Tue, Sep 29, 2015 at 08:35:08PM +1000, Michael Ellerman wrote:
> Commit 086b91d052eb ("scsi_dh: integrate into the core SCSI code")
> changed CONFIG_SCSI_DH from tristate to bool.
> 
> Our defconfigs have CONFIG_SCSI_DH=m, which the kconfig machinery warns
> us is invalid, but instead of converting it to =y it leaves it unset.
> This means we loose the CONFIG_SCSI_DH code and everything that depends
> on it.
> 
> So convert the values in the defconfigs to =y.
> 
> Fixes: 086b91d052eb ("scsi_dh: integrate into the core SCSI code")
> Signed-off-by: Michael Ellerman 

Looks good,

Reviewed-by: Christoph Hellwig 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 2/2] drivers/nvme: default to the IOMMU page size on Power

2015-10-02 Thread Christoph Hellwig
Hi Nishanth,

please expose this value through the generic DMA API instead of adding
architecture specific hacks to drivers.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 2/2] drivers/nvme: default to the IOMMU page size on Power

2015-10-02 Thread Christoph Hellwig
On Fri, Oct 02, 2015 at 10:39:47AM -0700, Nishanth Aravamudan wrote:
> Ok, I'm happy to do that instead -- what I struggled with is that I
> don't have enough knowledge of the various architectures to provide the
> right default implementation. It should be sufficient for the default to
> return PAGE_SHIFT, and on Power just override that to return the IOMMU
> table's page size? Since the only user will be the NVMe driver
> currently, that should be fine?

I think that's fine.

> Sorry for the less-than-ideal patch!

Np, it's a reasonable first attempt that we just need to refine.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 0/5 v2] Fix NVMe driver support on Power with 32-bit DMA

2015-10-03 Thread Christoph Hellwig
On Sat, Oct 03, 2015 at 06:51:06AM +1000, Benjamin Herrenschmidt wrote:
> On Fri, 2015-10-02 at 13:09 -0700, Nishanth Aravamudan wrote:
> 
> > 1) add a generic dma_get_page_shift implementation that just returns
> > PAGE_SHIFT
> 
> So you chose to return the granularity of the iommu to the driver
> rather than providing a way for the driver to request a specific
> alignment for DMA mappings. Any specific reason ?

At least for NVMe that's the way to go - it allows to set a page set in
the device which should fit the IOMMU page size.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/5 v2] dma-mapping: add generic dma_get_page_shift API

2015-10-06 Thread Christoph Hellwig
Do we need a function here or can we just have a IOMMU_PAGE_SHIFT define
with an #ifndef in common code?

Also not all architectures use dma-mapping-common.h yet, so you either
need to update all of those as well, or just add the #ifndef directly
to linux/dma-mapping.h.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [kbuild-all] [PATCH 4/5 v2] pseries/iommu: implement DDW-aware dma_get_page_shift

2015-10-08 Thread Christoph Hellwig
Hi Fengguang,

I think this proactive testing does a little more harm than good in
it's current form.  While offering testing for patches that aren't in
git trees and or by people that don't even have a git tree that the
build bots known about does seem useful, blindly doing it for every
patch against something that most likely isn't the right base seems
counter intertuitive.  We'll probaby need some annotation in the O/n
mail that asks for a test and sets a base tree to actually make it
useful.  With those few tweaks it should be really useful!

Maybe we should have a discussion about this at kernel summit?


On Thu, Oct 08, 2015 at 09:16:09AM +0800, Fengguang Wu wrote:
> And of course linux-kernel. More lists could be added in future.
> 
> Thanks,
> Fengguang
---end quoted text---
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/5 v2] dma-mapping: add generic dma_get_page_shift API

2015-10-14 Thread Christoph Hellwig
Hi Nishanth,

sorry for the late reply.

> > On Power, since it's technically variable, we'd need a function. So are
> > you suggesting define'ing it to a function just on Power and leaving it
> > a constant elsewhere?
> > 
> > I noticed that sparc has a IOMMU_PAGE_SHIFT already, fwiw.
> 
> Sorry, I should have been more specific -- I'm ready to spin out a v3,
> with a sparc-specific function.
> 
> Are you ok with leaving it a function for now (the only caller is in
> NVMe obviously).


I guess we do indeed need a function then.  I'll take a look at your
patch, but as long you found a way to avoid adding too much boilerplate
code it should be fine.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 0/5 v3] Fix NVMe driver support on Power with 32-bit DMA

2015-10-29 Thread Christoph Hellwig
On Wed, Oct 28, 2015 at 01:59:23PM +, Busch, Keith wrote:
> The "new" interface for all the other architectures is the same as the
> old one we've been using for the last 5 years.
> 
> I welcome x86 maintainer feedback to confirm virtual and DMA addresses
> have the same offset at 4k alignment, but I have to insist we don't
> break my currently working hardware to force their attention.

We had a quick cht about this issue and I think we simply should
default to a NVMe controler page size of 4k everywhere as that's the
safe default.  This is also what we do for RDMA Memory reigstrations and
it works fine there for SRP and iSER.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/1 v3] drivers/nvme: default to 4k device page size

2015-11-03 Thread Christoph Hellwig
On Fri, Oct 30, 2015 at 02:35:11PM -0700, Nishanth Aravamudan wrote:
> diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
> index ccc0c1f93daa..a9a5285bdb39 100644
> --- a/drivers/block/nvme-core.c
> +++ b/drivers/block/nvme-core.c
> @@ -1717,7 +1717,12 @@ static int nvme_configure_admin_queue(struct nvme_dev 
> *dev)
>   u32 aqa;
>   u64 cap = readq(&dev->bar->cap);
>   struct nvme_queue *nvmeq;
> - unsigned page_shift = PAGE_SHIFT;
> + /*
> +  * default to a 4K page size, with the intention to update this
> +  * path in the future to accomodate architectures with differing
> +  * kernel and IO page sizes.
> +  */
> + unsigned page_shift = 12;
>   unsigned dev_page_min = NVME_CAP_MPSMIN(cap) + 12;
>   unsigned dev_page_max = NVME_CAP_MPSMAX(cap) + 12;

Looks good as a start.  Note that all the MPSMIN/MAX checking could
be removed as NVMe devices must support 4k pages.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/1 v4] drivers/nvme: default to 4k device page size

2015-11-05 Thread Christoph Hellwig
Looks fine,

Reviewed-by: Christoph Hellwig 

... but I doubt we'll ever bother updating it.  Most architectures
with arger page sizes also have iommus and would need different settings
for different iommus vs direct mapping for very little gain.  There's a
reason why we never bothered for RDMA either.
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/1 v4] drivers/nvme: default to 4k device page size

2015-11-12 Thread Christoph Hellwig
Jens, Keith: any chance to get this to Linux for 4.4 (and -stable)?
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 1/1 v4] drivers/nvme: default to 4k device page size

2015-11-18 Thread Christoph Hellwig
On Fri, Nov 13, 2015 at 03:08:11PM +, Keith Busch wrote:
> On Thu, Nov 12, 2015 at 11:37:54PM -0800, Christoph Hellwig wrote:
> > Jens, Keith: any chance to get this to Linux for 4.4 (and -stable)?
> 
> I agreed, looks good to me.
> 
> Acked-by: Keith Busch 

Jens, can you pick this one for -rc2?
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: kernel BUG at drivers/scsi/scsi_lib.c:1096!

2015-11-19 Thread Christoph Hellwig
It's pretty much guaranteed a block layer bug, most likely in the
merge bios to request infrastucture where we don't obey the merging
limits properly.

Does either of you have a known good and first known bad kernel?
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: Question about Power8/9, PHB3/4 and setting of DMA mask

2019-04-03 Thread Christoph Hellwig
On Sun, Mar 31, 2019 at 12:50:21PM +0300, Oded Gabbay wrote:
> Due to some limitation in Goya, the driver first need to allocate a
> 2MB chunk in a DMA-able address under 39 bits and then we would like
> to move to using up to 48 bits. Therefore, the driver first tries to
> set the DMA mask to 39 bits, allocate the 2MB area and later on,
> change the DMA mask to 48 bits. On x86 this works fine.

You can't just change the DMA mask while you have active allocations,
this will fail for many implementations.


Re: [patch V2 07/15] powerpc/ps3: Convert half completion to rcuwait

2020-03-19 Thread Christoph Hellwig
On Wed, Mar 18, 2020 at 09:43:09PM +0100, Thomas Gleixner wrote:
> The PS3 notification interrupt and kthread use a hacked up completion to
> communicate. Since we're wanting to change the completion implementation and
> this is abuse anyway, replace it with a simple rcuwait since there is only 
> ever
> the one waiter.
> 
> AFAICT the kthread uses TASK_INTERRUPTIBLE to not increase loadavg, kthreads
> cannot receive signals by default and this one doesn't look different. Use
> TASK_IDLE instead.

I think the right fix here is to jut convert the thing to a threaded
interrupt handler and kill off the stupid kthread.

But I wonder how alive the whole PS3 support is to start with..


Re: [PATCH -v2] treewide: Rename "unencrypted" to "decrypted"

2020-03-19 Thread Christoph Hellwig
On Thu, Mar 19, 2020 at 11:16:57AM +0100, Borislav Petkov wrote:
> Hi,
> 
> here's v2 with build breakage fixed on ppc and s390 (obviously I can't
> grep :-\) and commit message extended to explain more why.

I thought we agreed that decrypted is absolutely the wrong term.

So NAK - if you want to change things it needs to go the other way.


Re: [patch V2 11/15] completion: Use simple wait queues

2020-03-20 Thread Christoph Hellwig
On Fri, Mar 20, 2020 at 10:25:41AM +1100, Julian Calaby wrote:
> > +++ b/drivers/usb/gadget/function/f_fs.c
> > @@ -1703,7 +1703,7 @@ static void ffs_data_put(struct ffs_data
> > pr_info("%s(): freeing\n", __func__);
> > ffs_data_clear(ffs);
> > BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
> > -  waitqueue_active(&ffs->ep0req_completion.wait) ||
> > +  swait_active(&ffs->ep0req_completion.wait) ||
> 
> This looks like some code is reaching deep into the dirty dark corners
> of the completion implementation, should there be some wrapper around
> this to hide that?

Or just remote it entirely..


generic DMA bypass flag v2

2020-03-20 Thread Christoph Hellwig
Hi all,

I've recently beeing chatting with Lu about using dma-iommu and
per-device DMA ops in the intel IOMMU driver, and one missing feature
in dma-iommu is a bypass mode where the direct mapping is used even
when an iommu is attached to improve performance.  The powerpc
code already has a similar mode, so I'd like to move it to the core
DMA mapping code.  As part of that I noticed that the current
powerpc code has a little bug in that it used the wrong check in the
dma_sync_* routines to see if the direct mapping code is used.

These two patches just add the generic code and move powerpc over,
the intel IOMMU bits will require a separate discussion.

The x86 AMD Gart code also has a bypass mode, but it is a lot
strange, so I'm not going to touch it for now.

Changes since v1:
 - rebased to the current dma-mapping-for-next tree


[PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-20 Thread Christoph Hellwig
Several IOMMU drivers have a bypass mode where they can use a direct
mapping if the devices DMA mask is large enough.  Add generic support
to the core dma-mapping code to do that to switch those drivers to
a common solution.

Signed-off-by: Christoph Hellwig 
---
 include/linux/device.h  |  6 ++
 include/linux/dma-mapping.h | 30 ++
 kernel/dma/mapping.c| 36 +++-
 3 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/include/linux/device.h b/include/linux/device.h
index 0cd7c647c16c..09be8bb2c4a6 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -525,6 +525,11 @@ struct dev_links_info {
  *   sync_state() callback.
  * @dma_coherent: this particular device is dma coherent, even if the
  * architecture supports non-coherent devices.
+ * @dma_ops_bypass: If set to %true then the dma_ops are bypassed for the
+ * streaming DMA operations (->map_* / ->unmap_* / ->sync_*),
+ * and optionall (if the coherent mask is large enough) also
+ * for dma allocations.  This flag is managed by the dma ops
+ * instance from ->dma_supported.
  *
  * At the lowest level, every device in a Linux system is represented by an
  * instance of struct device. The device structure contains the information
@@ -625,6 +630,7 @@ struct device {
 defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
booldma_coherent:1;
 #endif
+   booldma_ops_bypass : 1;
 };
 
 static inline struct device *kobj_to_dev(struct kobject *kobj)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 330ad58fbf4d..c3af0cf5e435 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -188,9 +188,15 @@ static inline int dma_mmap_from_global_coherent(struct 
vm_area_struct *vma,
 }
 #endif /* CONFIG_DMA_DECLARE_COHERENT */
 
-static inline bool dma_is_direct(const struct dma_map_ops *ops)
+/*
+ * Check if the devices uses a direct mapping for streaming DMA operations.
+ * This allows IOMMU drivers to set a bypass mode if the DMA mask is large
+ * enough.
+ */
+static inline bool dma_map_direct(struct device *dev,
+   const struct dma_map_ops *ops)
 {
-   return likely(!ops);
+   return likely(!ops) || dev->dma_ops_bypass;
 }
 
 /*
@@ -279,7 +285,7 @@ static inline dma_addr_t dma_map_page_attrs(struct device 
*dev,
dma_addr_t addr;
 
BUG_ON(!valid_dma_direction(dir));
-   if (dma_is_direct(ops))
+   if (dma_map_direct(dev, ops))
addr = dma_direct_map_page(dev, page, offset, size, dir, attrs);
else
addr = ops->map_page(dev, page, offset, size, dir, attrs);
@@ -294,7 +300,7 @@ static inline void dma_unmap_page_attrs(struct device *dev, 
dma_addr_t addr,
const struct dma_map_ops *ops = get_dma_ops(dev);
 
BUG_ON(!valid_dma_direction(dir));
-   if (dma_is_direct(ops))
+   if (dma_map_direct(dev, ops))
dma_direct_unmap_page(dev, addr, size, dir, attrs);
else if (ops->unmap_page)
ops->unmap_page(dev, addr, size, dir, attrs);
@@ -313,7 +319,7 @@ static inline int dma_map_sg_attrs(struct device *dev, 
struct scatterlist *sg,
int ents;
 
BUG_ON(!valid_dma_direction(dir));
-   if (dma_is_direct(ops))
+   if (dma_map_direct(dev, ops))
ents = dma_direct_map_sg(dev, sg, nents, dir, attrs);
else
ents = ops->map_sg(dev, sg, nents, dir, attrs);
@@ -331,7 +337,7 @@ static inline void dma_unmap_sg_attrs(struct device *dev, 
struct scatterlist *sg
 
BUG_ON(!valid_dma_direction(dir));
debug_dma_unmap_sg(dev, sg, nents, dir);
-   if (dma_is_direct(ops))
+   if (dma_map_direct(dev, ops))
dma_direct_unmap_sg(dev, sg, nents, dir, attrs);
else if (ops->unmap_sg)
ops->unmap_sg(dev, sg, nents, dir, attrs);
@@ -352,7 +358,7 @@ static inline dma_addr_t dma_map_resource(struct device 
*dev,
if (WARN_ON_ONCE(pfn_valid(PHYS_PFN(phys_addr
return DMA_MAPPING_ERROR;
 
-   if (dma_is_direct(ops))
+   if (dma_map_direct(dev, ops))
addr = dma_direct_map_resource(dev, phys_addr, size, dir, 
attrs);
else if (ops->map_resource)
addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
@@ -368,7 +374,7 @@ static inline void dma_unmap_resource(struct device *dev, 
dma_addr_t addr,
const struct dma_map_ops *ops = get_dma_ops(dev);
 
BUG_ON(!valid_dma_direction(dir));
-   if (!dma_is_direct(ops) && ops->unmap_resource)
+   if (!dma_map_direct(dev, ops) && ops->unmap_resource)
ops->unmap_resource(dev, addr, size, dir, attrs);
debug_dma_unmap_resource(dev, addr, size, dir);
 }
@@ -380,7 +3

[PATCH 2/2] powerpc: use the generic dma_ops_bypass mode

2020-03-20 Thread Christoph Hellwig
Use the DMA API bypass mechanism for direct window mappings.  This uses
common code and speed up the direct mapping case by avoiding indirect
calls just when not using dma ops at all.  It also fixes a problem where
the sync_* methods were using the bypass check for DMA allocations, but
those are part of the streaming ops.

Note that this patch loses the DMA_ATTR_WEAK_ORDERING override, which
has never been well defined, as is only used by a few drivers, which
IIRC never showed up in the typical Cell blade setups that are affected
by the ordering workaround.

Fixes: efd176a04bef ("powerpc/pseries/dma: Allow SWIOTLB")
Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/include/asm/device.h |  5 --
 arch/powerpc/kernel/dma-iommu.c   | 90 ---
 2 files changed, 9 insertions(+), 86 deletions(-)

diff --git a/arch/powerpc/include/asm/device.h 
b/arch/powerpc/include/asm/device.h
index 266542769e4b..452402215e12 100644
--- a/arch/powerpc/include/asm/device.h
+++ b/arch/powerpc/include/asm/device.h
@@ -18,11 +18,6 @@ struct iommu_table;
  * drivers/macintosh/macio_asic.c
  */
 struct dev_archdata {
-   /*
-* Set to %true if the dma_iommu_ops are requested to use a direct
-* window instead of dynamically mapping memory.
-*/
-   booliommu_bypass : 1;
/*
 * These two used to be a union. However, with the hybrid ops we need
 * both so here we store both a DMA offset for direct mappings and
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index e486d1d78de2..569fecd7b5b2 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -14,23 +14,6 @@
  * Generic iommu implementation
  */
 
-/*
- * The coherent mask may be smaller than the real mask, check if we can
- * really use a direct window.
- */
-static inline bool dma_iommu_alloc_bypass(struct device *dev)
-{
-   return dev->archdata.iommu_bypass && !iommu_fixed_is_weak &&
-   dma_direct_supported(dev, dev->coherent_dma_mask);
-}
-
-static inline bool dma_iommu_map_bypass(struct device *dev,
-   unsigned long attrs)
-{
-   return dev->archdata.iommu_bypass &&
-   (!iommu_fixed_is_weak || (attrs & DMA_ATTR_WEAK_ORDERING));
-}
-
 /* Allocates a contiguous real buffer and creates mappings over it.
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
@@ -39,8 +22,6 @@ static void *dma_iommu_alloc_coherent(struct device *dev, 
size_t size,
  dma_addr_t *dma_handle, gfp_t flag,
  unsigned long attrs)
 {
-   if (dma_iommu_alloc_bypass(dev))
-   return dma_direct_alloc(dev, size, dma_handle, flag, attrs);
return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
dma_handle, dev->coherent_dma_mask, flag,
dev_to_node(dev));
@@ -50,11 +31,7 @@ static void dma_iommu_free_coherent(struct device *dev, 
size_t size,
void *vaddr, dma_addr_t dma_handle,
unsigned long attrs)
 {
-   if (dma_iommu_alloc_bypass(dev))
-   dma_direct_free(dev, size, vaddr, dma_handle, attrs);
-   else
-   iommu_free_coherent(get_iommu_table_base(dev), size, vaddr,
-   dma_handle);
+   iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
 }
 
 /* Creates TCEs for a user provided buffer.  The user buffer must be
@@ -67,9 +44,6 @@ static dma_addr_t dma_iommu_map_page(struct device *dev, 
struct page *page,
 enum dma_data_direction direction,
 unsigned long attrs)
 {
-   if (dma_iommu_map_bypass(dev, attrs))
-   return dma_direct_map_page(dev, page, offset, size, direction,
-   attrs);
return iommu_map_page(dev, get_iommu_table_base(dev), page, offset,
  size, dma_get_mask(dev), direction, attrs);
 }
@@ -79,11 +53,8 @@ static void dma_iommu_unmap_page(struct device *dev, 
dma_addr_t dma_handle,
 size_t size, enum dma_data_direction direction,
 unsigned long attrs)
 {
-   if (!dma_iommu_map_bypass(dev, attrs))
-   iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size,
-   direction,  attrs);
-   else
-   dma_direct_unmap_page(dev, dma_handle, size, direction, attrs);
+   iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size, direction,
+attrs);
 }
 
 
@@ -91,8 +62,6 @@ static int dma_iommu_map_sg(struct device *dev, struct 
scatterlist *sglist,
 

Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-23 Thread Christoph Hellwig
On Mon, Mar 23, 2020 at 12:28:34PM +1100, Alexey Kardashevskiy wrote:

[full quote deleted, please follow proper quoting rules]

> > +static bool dma_alloc_direct(struct device *dev, const struct dma_map_ops 
> > *ops)
> > +{
> > +   if (!ops)
> > +   return true;
> > +
> > +   /*
> > +* Allows IOMMU drivers to bypass dynamic translations if the DMA mask
> > +* is large enough.
> > +*/
> > +   if (dev->dma_ops_bypass) {
> > +   if (min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit) >=
> > +   dma_direct_get_required_mask(dev))
> > +   return true;
> > +   }
> 
> 
> Why not do this in dma_map_direct() as well?

Mostly beacuse it is a relatively expensive operation, including a
fls64.

> Or simply have just one dma_map_direct()?

What do you mean with that?

> And one more general question - we need a way to use non-direct IOMMU
> for RAM above certain limit.
> 
> Let's say we have a system with:
> 0 .. 0x1..
> 0x100.. .. 0x101..
> 
> 2x4G, each is 1TB aligned. And we can map directly only the first 4GB
> (because of the maximum IOMMU table size) but not the other. And 1:1 on
> that "pseries" is done with offset=0x0800....
> 
> So we want to check every bus address against dev->bus_dma_limit, not
> dev->coherent_dma_mask. In the example above I'd set bus_dma_limit to
> 0x0800.0001.. and 1:1 mapping for the second 4GB would not be
> tried. Does this sound reasonable? Thanks,

bus_dma_limit is just another limiting factor applied on top of
coherent_dma_mask or dma_mask respectively.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-23 Thread Christoph Hellwig
On Mon, Mar 23, 2020 at 09:37:05AM +0100, Christoph Hellwig wrote:
> > > + /*
> > > +  * Allows IOMMU drivers to bypass dynamic translations if the DMA mask
> > > +  * is large enough.
> > > +  */
> > > + if (dev->dma_ops_bypass) {
> > > + if (min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit) >=
> > > + dma_direct_get_required_mask(dev))
> > > + return true;
> > > + }
> > 
> > 
> > Why not do this in dma_map_direct() as well?
> 
> Mostly beacuse it is a relatively expensive operation, including a
> fls64.

Which I guess isn't too bad compared to a dynamic IOMMU mapping.  Can
you just send a draft patch for what you'd like to see for ppc?


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-23 Thread Christoph Hellwig
On Mon, Mar 23, 2020 at 12:14:08PM +, Robin Murphy wrote:
> On 2020-03-20 2:16 pm, Christoph Hellwig wrote:
>> Several IOMMU drivers have a bypass mode where they can use a direct
>> mapping if the devices DMA mask is large enough.  Add generic support
>> to the core dma-mapping code to do that to switch those drivers to
>> a common solution.
>
> Hmm, this is _almost_, but not quite the same as the case where drivers are 
> managing their own IOMMU mappings, but still need to use streaming DMA for 
> cache maintenance on the underlying pages.

In that case they should simply not call the DMA API at all.  We'll just
need versions of the cache maintainance APIs that tie in with the raw
IOMMU API.

> For that we need the ops bypass 
> to be a "true" bypass and also avoid SWIOTLB regardless of the device's DMA 
> mask. That behaviour should in fact be fine for the opportunistic bypass 
> case here as well, since the mask being "big enough" implies by definition 
> that this should never need to bounce either.

In practice it does.  But that means adding yet another code path
vs the simple direct call to dma_direct_* vs calling the DMA ops
which I'd rather avoid.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-23 Thread Christoph Hellwig
On Mon, Mar 23, 2020 at 07:58:01PM +1100, Alexey Kardashevskiy wrote:
> >> 0x100.. .. 0x101..
> >>
> >> 2x4G, each is 1TB aligned. And we can map directly only the first 4GB
> >> (because of the maximum IOMMU table size) but not the other. And 1:1 on
> >> that "pseries" is done with offset=0x0800....
> >>
> >> So we want to check every bus address against dev->bus_dma_limit, not
> >> dev->coherent_dma_mask. In the example above I'd set bus_dma_limit to
> >> 0x0800.0001.. and 1:1 mapping for the second 4GB would not be
> >> tried. Does this sound reasonable? Thanks,
> > 
> > bus_dma_limit is just another limiting factor applied on top of
> > coherent_dma_mask or dma_mask respectively.
> 
> This is not enough for the task: in my example, I'd set bus limit to
> 0x0800.0001.. but this would disable bypass for all RAM
> addresses - the first and the second 4GB blocks.

So what about something like the version here:

http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/dma-bypass.3


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-23 Thread Christoph Hellwig
On Mon, Mar 23, 2020 at 09:07:38PM +0530, Aneesh Kumar K.V wrote:
> 
> This is what I was trying, but considering I am new to DMA subsystem, I
> am not sure I got all the details correct. The idea is to look at the
> cpu addr and see if that can be used in direct map fashion(is
> bus_dma_limit the right restriction here?) if not fallback to dynamic
> IOMMU mapping.

I don't think we can throw all these complications into the dma
mapping code.  At some point I also wonder what the point is,
especially for scatterlist mappings, where the iommu can coalesce.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-24 Thread Christoph Hellwig
On Tue, Mar 24, 2020 at 02:37:59PM +1100, Alexey Kardashevskiy wrote:
> dma_alloc_direct() and dma_map_direct() do the same thing now which is
> good, did I miss anything else?

dma_alloc_direct looks at coherent_dma_mask, dma_map_direct looks
at dma_mask.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-24 Thread Christoph Hellwig
On Tue, Mar 24, 2020 at 02:05:54PM +1100, Alexey Kardashevskiy wrote:
> This is for persistent memory which you can DMA to/from but yet it does
> not appear in the system as a normal memory and therefore requires
> special handling anyway (O_DIRECT or DAX, I do not know the exact
> mechanics). All other devices in the system should just run as usual,
> i.e. use 1:1 mapping if possible.

On other systems (x86 and arm) pmem as long as it is page backed does
not require any special handling.  This must be some weird way powerpc
fucked up again, and I suspect you'll have to suffer from it.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-24 Thread Christoph Hellwig
On Tue, Mar 24, 2020 at 12:00:09PM +0530, Aneesh Kumar K.V wrote:
> dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
>   unsigned long offset, size_t size, enum dma_data_direction dir,
>   unsigned long attrs)
> {
>   phys_addr_t phys = page_to_phys(page) + offset;
>   dma_addr_t dma_addr = phys_to_dma(dev, phys);
> 
>   if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
>   return iommu_map(dev, phys, size, dir, attrs);
> 
>   return DMA_MAPPING_ERROR;

If powerpc hardware / firmware people really come up with crap that
stupid you'll have to handle it yourself and will always pay the
indirect call penality.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-03-25 Thread Christoph Hellwig
On Wed, Mar 25, 2020 at 03:51:36PM +1100, Alexey Kardashevskiy wrote:
> >> This is for persistent memory which you can DMA to/from but yet it does
> >> not appear in the system as a normal memory and therefore requires
> >> special handling anyway (O_DIRECT or DAX, I do not know the exact
> >> mechanics). All other devices in the system should just run as usual,
> >> i.e. use 1:1 mapping if possible.
> > 
> > On other systems (x86 and arm) pmem as long as it is page backed does
> > not require any special handling.  This must be some weird way powerpc
> > fucked up again, and I suspect you'll have to suffer from it.
> 
> 
> It does not matter if it is backed by pages or not, the problem may also
> appear if we wanted for example p2p PCI via IOMMU (between PHBs) and
> MMIO might be mapped way too high in the system address space and make
> 1:1 impossible.

How can it be mapped too high for a direct mapping with a 64-bit DMA
mask?


Re: [PATCH] powerpc/44x: Make AKEBONO depends on NET

2020-03-31 Thread Christoph Hellwig
Why would a board select a network driver?  That is what defconfig
files are for!  I thin kthe select should just go away.


Re: [PATCH 1/2] dma-mapping: add a dma_ops_bypass flag to struct device

2020-04-06 Thread Christoph Hellwig
On Fri, Apr 03, 2020 at 07:38:11PM +1100, Alexey Kardashevskiy wrote:
> 
> 
> On 26/03/2020 12:26, Alexey Kardashevskiy wrote:
> > 
> > 
> > On 25/03/2020 19:37, Christoph Hellwig wrote:
> >> On Wed, Mar 25, 2020 at 03:51:36PM +1100, Alexey Kardashevskiy wrote:
> >>>>> This is for persistent memory which you can DMA to/from but yet it does
> >>>>> not appear in the system as a normal memory and therefore requires
> >>>>> special handling anyway (O_DIRECT or DAX, I do not know the exact
> >>>>> mechanics). All other devices in the system should just run as usual,
> >>>>> i.e. use 1:1 mapping if possible.
> >>>>
> >>>> On other systems (x86 and arm) pmem as long as it is page backed does
> >>>> not require any special handling.  This must be some weird way powerpc
> >>>> fucked up again, and I suspect you'll have to suffer from it.
> >>>
> >>>
> >>> It does not matter if it is backed by pages or not, the problem may also
> >>> appear if we wanted for example p2p PCI via IOMMU (between PHBs) and
> >>> MMIO might be mapped way too high in the system address space and make
> >>> 1:1 impossible.
> >>
> >> How can it be mapped too high for a direct mapping with a 64-bit DMA
> >> mask?
> > 
> > The window size is limited and often it is not even sparse. It requires
> > an 8 byte entry per an IOMMU page (which is most commonly is 64k max) so
> > 1TB limit (a guest RAM size) is a quite real thing. MMIO is mapped to
> > guest physical address space outside of this 1TB (on PPC).
> > 
> > 
> 
> I am trying now this approach on top of yours "dma-bypass.3" (it is
> "wip", needs an upper boundary check):
> 
> https://github.com/aik/linux/commit/49d73c7771e3f6054804f6cfa80b4e320111662d
> 
> Do you see any serious problem with this approach? Thanks!

Do you have a link to the whole branch?  The github UI is unfortunately
unusable for that (or I'm missing something).


remove set_fs calls from the exec and coredump code

2020-04-06 Thread Christoph Hellwig
Hi all,

this series gets rid of playing with the address limit in the exec and
coredump code.  Most of this was fairly trivial, the biggest changes are
those to the spufs coredump code.


[PATCH 1/6] powerpc/spufs: simplify spufs core dumping

2020-04-06 Thread Christoph Hellwig
Replace the coredump ->read method with a ->dump method that must call
dump_emit itself.  That way we avoid a buffer allocation an messing with
set_fs() to call into code that is intended to deal with user buffers.
For the ->get case we can now use a small on-stack buffer and avoid
memory allocations as well.

Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/platforms/cell/spufs/coredump.c |  87 ++
 arch/powerpc/platforms/cell/spufs/file.c | 273 ++-
 arch/powerpc/platforms/cell/spufs/spufs.h|   3 +-
 3 files changed, 170 insertions(+), 193 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c 
b/arch/powerpc/platforms/cell/spufs/coredump.c
index 8b3296b62f65..3b75e8f60609 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -21,22 +21,6 @@
 
 #include "spufs.h"
 
-static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
-   size_t size, loff_t *off)
-{
-   u64 data;
-   int ret;
-
-   if (spufs_coredump_read[num].read)
-   return spufs_coredump_read[num].read(ctx, buffer, size, off);
-
-   data = spufs_coredump_read[num].get(ctx);
-   ret = snprintf(buffer, size, "0x%.16llx", data);
-   if (ret >= size)
-   return size;
-   return ++ret; /* count trailing NULL */
-}
-
 static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
 {
int i, sz, total = 0;
@@ -118,58 +102,43 @@ int spufs_coredump_extra_notes_size(void)
 static int spufs_arch_write_note(struct spu_context *ctx, int i,
  struct coredump_params *cprm, int dfd)
 {
-   loff_t pos = 0;
-   int sz, rc, total = 0;
-   const int bufsz = PAGE_SIZE;
-   char *name;
-   char fullname[80], *buf;
+   size_t sz = spufs_coredump_read[i].size;
+   char fullname[80];
struct elf_note en;
-   size_t skip;
-
-   buf = (void *)get_zeroed_page(GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
+   size_t ret;
 
-   name = spufs_coredump_read[i].name;
-   sz = spufs_coredump_read[i].size;
-
-   sprintf(fullname, "SPU/%d/%s", dfd, name);
+   sprintf(fullname, "SPU/%d/%s", dfd, spufs_coredump_read[i].name);
en.n_namesz = strlen(fullname) + 1;
en.n_descsz = sz;
en.n_type = NT_SPU;
 
if (!dump_emit(cprm, &en, sizeof(en)))
-   goto Eio;
-
+   return -EIO;
if (!dump_emit(cprm, fullname, en.n_namesz))
-   goto Eio;
-
+   return -EIO;
if (!dump_align(cprm, 4))
-   goto Eio;
-
-   do {
-   rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
-   if (rc > 0) {
-   if (!dump_emit(cprm, buf, rc))
-   goto Eio;
-   total += rc;
-   }
-   } while (rc == bufsz && total < sz);
-
-   if (rc < 0)
-   goto out;
-
-   skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
-   if (!dump_skip(cprm, skip))
-   goto Eio;
-
-   rc = 0;
-out:
-   free_page((unsigned long)buf);
-   return rc;
-Eio:
-   free_page((unsigned long)buf);
-   return -EIO;
+   return -EIO;
+
+   if (spufs_coredump_read[i].dump) {
+   ret = spufs_coredump_read[i].dump(ctx, cprm);
+   if (ret < 0)
+   return ret;
+   } else {
+   char buf[32];
+
+   ret = snprintf(buf, sizeof(buf), "0x%.16llx",
+  spufs_coredump_read[i].get(ctx));
+   if (ret >= sizeof(buf))
+   return sizeof(buf);
+
+   /* count trailing the NULL: */
+   if (!dump_emit(cprm, buf, ret + 1))
+   return -EIO;
+   }
+
+   if (!dump_skip(cprm, roundup(cprm->pos - ret + sz, 4) - cprm->pos))
+   return -EIO;
+   return 0;
 }
 
 int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c 
b/arch/powerpc/platforms/cell/spufs/file.c
index c0f950a3f4e1..d9574c4b1347 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -9,6 +9,7 @@
 
 #undef DEBUG
 
+#include 
 #include 
 #include 
 #include 
@@ -129,6 +130,14 @@ static ssize_t spufs_attr_write(struct file *file, const 
char __user *buf,
return ret;
 }
 
+static ssize_t spufs_dump_emit(struct coredump_params *cprm, void *buf,
+   size_t size)
+{
+   if (!dump_emit(cprm, buf, size))
+   return -EIO;
+   return size;
+}
+
 #define DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
 static int __fops ## _open(struct inode *inode, struct file

[PATCH 2/6] binfmt_elf: open code copy_siginfo_to_user to kernelspace buffer

2020-04-06 Thread Christoph Hellwig
Instead of messing with the address limit just open code the trivial
memcpy + memset logic.

Signed-off-by: Christoph Hellwig 
---
 fs/binfmt_elf.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index f4713ea76e82..d744ce9a4b52 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1556,10 +1556,9 @@ static void fill_auxv_note(struct memelfnote *note, 
struct mm_struct *mm)
 static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t 
*csigdata,
const kernel_siginfo_t *siginfo)
 {
-   mm_segment_t old_fs = get_fs();
-   set_fs(KERNEL_DS);
-   copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo);
-   set_fs(old_fs);
+   memcpy(csigdata, siginfo, sizeof(struct kernel_siginfo));
+   memset((char *)csigdata + sizeof(struct kernel_siginfo), 0,
+   SI_EXPANSION_SIZE);
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
 }
 
-- 
2.25.1



[PATCH 3/6] binfmt_elf: remove the set_fs(KERNEL_DS) in elf_core_dump

2020-04-06 Thread Christoph Hellwig
There is no logic in elf_core_dump itself that uses uaccess routines
on kernel pointers, the file writes are nicely encapsulated in dump_emit
which does its own set_fs.

Signed-off-by: Christoph Hellwig 
---
 fs/binfmt_elf.c | 40 +---
 1 file changed, 13 insertions(+), 27 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d744ce9a4b52..ef9f68bab7be 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1355,7 +1355,6 @@ static unsigned long vma_dump_size(struct vm_area_struct 
*vma,
vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
u32 __user *header = (u32 __user *) vma->vm_start;
u32 word;
-   mm_segment_t fs = get_fs();
/*
 * Doing it this way gets the constant folded by GCC.
 */
@@ -1368,14 +1367,8 @@ static unsigned long vma_dump_size(struct vm_area_struct 
*vma,
magic.elfmag[EI_MAG1] = ELFMAG1;
magic.elfmag[EI_MAG2] = ELFMAG2;
magic.elfmag[EI_MAG3] = ELFMAG3;
-   /*
-* Switch to the user "segment" for get_user(),
-* then put back what elf_core_dump() had in place.
-*/
-   set_fs(USER_DS);
if (unlikely(get_user(word, header)))
word = 0;
-   set_fs(fs);
if (word == magic.cmp)
return PAGE_SIZE;
}
@@ -2185,7 +2178,6 @@ static void fill_extnum_info(struct elfhdr *elf, struct 
elf_shdr *shdr4extnum,
 static int elf_core_dump(struct coredump_params *cprm)
 {
int has_dumped = 0;
-   mm_segment_t fs;
int segs, i;
size_t vma_data_size = 0;
struct vm_area_struct *vma, *gate_vma;
@@ -2238,9 +2230,6 @@ static int elf_core_dump(struct coredump_params *cprm)
 
has_dumped = 1;
 
-   fs = get_fs();
-   set_fs(KERNEL_DS);
-
offset += sizeof(elf);  /* Elf header */
offset += segs * sizeof(struct elf_phdr);   /* Program headers */
 
@@ -2252,7 +2241,7 @@ static int elf_core_dump(struct coredump_params *cprm)
 
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
if (!phdr4note)
-   goto end_coredump;
+   goto cleanup;
 
fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz;
@@ -2267,7 +2256,7 @@ static int elf_core_dump(struct coredump_params *cprm)
vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)),
  GFP_KERNEL);
if (!vma_filesz)
-   goto end_coredump;
+   goto cleanup;
 
for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
vma = next_vma(vma, gate_vma)) {
@@ -2285,17 +2274,17 @@ static int elf_core_dump(struct coredump_params *cprm)
if (e_phnum == PN_XNUM) {
shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
if (!shdr4extnum)
-   goto end_coredump;
+   goto cleanup;
fill_extnum_info(&elf, shdr4extnum, e_shoff, segs);
}
 
offset = dataoff;
 
if (!dump_emit(cprm, &elf, sizeof(elf)))
-   goto end_coredump;
+   goto cleanup;
 
if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
-   goto end_coredump;
+   goto cleanup;
 
/* Write program headers for segments dump */
for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
@@ -2317,22 +2306,22 @@ static int elf_core_dump(struct coredump_params *cprm)
phdr.p_align = ELF_EXEC_PAGESIZE;
 
if (!dump_emit(cprm, &phdr, sizeof(phdr)))
-   goto end_coredump;
+   goto cleanup;
}
 
if (!elf_core_write_extra_phdrs(cprm, offset))
-   goto end_coredump;
+   goto cleanup;
 
/* write out the notes section */
if (!write_note_info(&info, cprm))
-   goto end_coredump;
+   goto cleanup;
 
if (elf_coredump_extra_notes_write(cprm))
-   goto end_coredump;
+   goto cleanup;
 
/* Align to page */
if (!dump_skip(cprm, dataoff - cprm->pos))
-   goto end_coredump;
+   goto cleanup;
 
for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
vma = next_vma(vma, gate_vma)) {
@@ -2354,22 +2343,19 @@ static int elf_core_dump(struct coredump_params *cprm)
} else
stop = !dump_skip(cprm, PAGE_SIZE);
if (stop)
-   goto end_coredump;
+   goto cleanup;
}
 

[PATCH 4/6] binfmt_elf_fdpic: remove the set_fs(KERNEL_DS) in elf_fdpic_core_dump

2020-04-06 Thread Christoph Hellwig
There is no logic in elf_fdpic_core_dump itself that uses uaccess
routines on kernel pointers, the file writes are nicely encapsulated in
dump_emit which does its own set_fs.

Signed-off-by: Christoph Hellwig 
---
 fs/binfmt_elf_fdpic.c | 31 ---
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 240f3543..c62c17a5c34a 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1549,7 +1549,6 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
 {
 #defineNUM_NOTES   6
int has_dumped = 0;
-   mm_segment_t fs;
int segs;
int i;
struct vm_area_struct *vma;
@@ -1678,9 +1677,6 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
  "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
 #endif
 
-   fs = get_fs();
-   set_fs(KERNEL_DS);
-
offset += sizeof(*elf); /* Elf header */
offset += segs * sizeof(struct elf_phdr);   /* Program headers */
 
@@ -1695,7 +1691,7 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
 
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
if (!phdr4note)
-   goto end_coredump;
+   goto cleanup;
 
fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz;
@@ -1711,17 +1707,17 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
if (e_phnum == PN_XNUM) {
shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
if (!shdr4extnum)
-   goto end_coredump;
+   goto cleanup;
fill_extnum_info(elf, shdr4extnum, e_shoff, segs);
}
 
offset = dataoff;
 
if (!dump_emit(cprm, elf, sizeof(*elf)))
-   goto end_coredump;
+   goto cleanup;
 
if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
-   goto end_coredump;
+   goto cleanup;
 
/* write program headers for segments dump */
for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
@@ -1745,16 +1741,16 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
phdr.p_align = ELF_EXEC_PAGESIZE;
 
if (!dump_emit(cprm, &phdr, sizeof(phdr)))
-   goto end_coredump;
+   goto cleanup;
}
 
if (!elf_core_write_extra_phdrs(cprm, offset))
-   goto end_coredump;
+   goto cleanup;
 
/* write out the notes section */
for (i = 0; i < numnote; i++)
if (!writenote(notes + i, cprm))
-   goto end_coredump;
+   goto cleanup;
 
/* write out the thread status notes section */
list_for_each(t, &thread_list) {
@@ -1763,21 +1759,21 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
 
for (i = 0; i < tmp->num_notes; i++)
if (!writenote(&tmp->notes[i], cprm))
-   goto end_coredump;
+   goto cleanup;
}
 
if (!dump_skip(cprm, dataoff - cprm->pos))
-   goto end_coredump;
+   goto cleanup;
 
if (!elf_fdpic_dump_segments(cprm))
-   goto end_coredump;
+   goto cleanup;
 
if (!elf_core_write_extra_data(cprm))
-   goto end_coredump;
+   goto cleanup;
 
if (e_phnum == PN_XNUM) {
if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
-   goto end_coredump;
+   goto cleanup;
}
 
if (cprm->file->f_pos != offset) {
@@ -1787,9 +1783,6 @@ static int elf_fdpic_core_dump(struct coredump_params 
*cprm)
   cprm->file->f_pos, offset);
}
 
-end_coredump:
-   set_fs(fs);
-
 cleanup:
while (!list_empty(&thread_list)) {
struct list_head *tmp = thread_list.next;
-- 
2.25.1



[PATCH 5/6] exec: simplify the copy_strings_kernel calling convention

2020-04-06 Thread Christoph Hellwig
copy_strings_kernel is always used with a single argument,
adjust the calling convention to that.

Signed-off-by: Christoph Hellwig 
---
 fs/binfmt_em86.c|  6 +++---
 fs/binfmt_misc.c|  4 ++--
 fs/binfmt_script.c  |  6 +++---
 fs/exec.c   | 13 ++---
 include/linux/binfmts.h |  3 +--
 5 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c
index 466497860c62..f33fa668c91f 100644
--- a/fs/binfmt_em86.c
+++ b/fs/binfmt_em86.c
@@ -68,15 +68,15 @@ static int load_em86(struct linux_binprm *bprm)
 * user environment and arguments are stored.
 */
remove_arg_zero(bprm);
-   retval = copy_strings_kernel(1, &bprm->filename, bprm);
+   retval = copy_string_kernel(bprm->filename, bprm);
if (retval < 0) return retval; 
bprm->argc++;
if (i_arg) {
-   retval = copy_strings_kernel(1, &i_arg, bprm);
+   retval = copy_string_kernel(i_arg, bprm);
if (retval < 0) return retval; 
bprm->argc++;
}
-   retval = copy_strings_kernel(1, &i_name, bprm);
+   retval = copy_string_kernel(i_name, bprm);
if (retval < 0) return retval;
bprm->argc++;
 
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index cdb45829354d..b15257d8ff5e 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -190,13 +190,13 @@ static int load_misc_binary(struct linux_binprm *bprm)
bprm->file = NULL;
}
/* make argv[1] be the path to the binary */
-   retval = copy_strings_kernel(1, &bprm->interp, bprm);
+   retval = copy_string_kernel(bprm->interp, bprm);
if (retval < 0)
goto error;
bprm->argc++;
 
/* add the interp as argv[0] */
-   retval = copy_strings_kernel(1, &fmt->interpreter, bprm);
+   retval = copy_string_kernel(fmt->interpreter, bprm);
if (retval < 0)
goto error;
bprm->argc++;
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index e9e6a6f4a35f..c4fb7f52a46e 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -117,17 +117,17 @@ static int load_script(struct linux_binprm *bprm)
retval = remove_arg_zero(bprm);
if (retval)
return retval;
-   retval = copy_strings_kernel(1, &bprm->interp, bprm);
+   retval = copy_string_kernel(bprm->interp, bprm);
if (retval < 0)
return retval;
bprm->argc++;
if (i_arg) {
-   retval = copy_strings_kernel(1, &i_arg, bprm);
+   retval = copy_string_kernel(i_arg, bprm);
if (retval < 0)
return retval;
bprm->argc++;
}
-   retval = copy_strings_kernel(1, &i_name, bprm);
+   retval = copy_string_kernel(i_name, bprm);
if (retval)
return retval;
bprm->argc++;
diff --git a/fs/exec.c b/fs/exec.c
index 06b4c550af5d..b2a77d5acede 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -588,24 +588,23 @@ static int copy_strings(int argc, struct user_arg_ptr 
argv,
 }
 
 /*
- * Like copy_strings, but get argv and its values from kernel memory.
+ * Copy and argument/environment string from the kernel to the processes stack.
  */
-int copy_strings_kernel(int argc, const char *const *__argv,
-   struct linux_binprm *bprm)
+int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
 {
int r;
mm_segment_t oldfs = get_fs();
struct user_arg_ptr argv = {
-   .ptr.native = (const char __user *const  __user *)__argv,
+   .ptr.native = (const char __user *const  __user *)&arg,
};
 
set_fs(KERNEL_DS);
-   r = copy_strings(argc, argv, bprm);
+   r = copy_strings(1, argv, bprm);
set_fs(oldfs);
 
return r;
 }
-EXPORT_SYMBOL(copy_strings_kernel);
+EXPORT_SYMBOL(copy_string_kernel);
 
 #ifdef CONFIG_MMU
 
@@ -1863,7 +1862,7 @@ static int __do_execve_file(int fd, struct filename 
*filename,
if (retval < 0)
goto out;
 
-   retval = copy_strings_kernel(1, &bprm->filename, bprm);
+   retval = copy_string_kernel(bprm->filename, bprm);
if (retval < 0)
goto out;
 
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index a345d9fed3d8..3d3afe094c97 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -144,8 +144,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm,
 extern int transfer_args_to_stack(struct linux_binprm *bprm,
  unsigned long *sp_location);
 extern int bprm_change_interp(const char *interp, struct linux_binprm *bprm);
-extern int copy_strings_kernel(int argc, const char *const *argv,
-  struct linux_binprm *bprm);
+i

  1   2   3   4   5   6   7   8   9   10   >