2018-07-19 12:58:36

by Christoph Hellwig

[permalink] [raw]
Subject: use the generic dma-noncoherent code for hexagon

Hi Richard,

can you review these patches to switch hexagon to use the generic
dma-noncoherent code? All the requirements are in mainline already
and we've switched various architectures over to it already.


2018-07-19 12:57:55

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 3/3] hexagon: use generic dma_noncoherent_ops

Switch to the generic noncoherent direct mapping implementation.

Signed-off-by: Christoph Hellwig <[email protected]>
---
arch/hexagon/Kconfig | 2 +
arch/hexagon/include/asm/Kbuild | 1 +
arch/hexagon/include/asm/dma-mapping.h | 40 -------
arch/hexagon/kernel/dma.c | 148 ++-----------------------
4 files changed, 11 insertions(+), 180 deletions(-)
delete mode 100644 arch/hexagon/include/asm/dma-mapping.h

diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 37adb2003033..bcbdcb32935c 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -4,6 +4,7 @@ comment "Linux Kernel Configuration for Hexagon"

config HEXAGON
def_bool y
+ select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select HAVE_OPROFILE
# Other pending projects/to-do items.
# select HAVE_REGS_AND_STACK_ACCESS_API
@@ -28,6 +29,7 @@ config HEXAGON
select GENERIC_CLOCKEVENTS_BROADCAST
select MODULES_USE_ELF_RELA
select GENERIC_CPU_DEVICES
+ select DMA_NONCOHERENT_OPS
---help---
Qualcomm Hexagon is a processor architecture designed for high
performance and low power across a wide variety of applications.
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index dd2fd9c0d292..47c4da3d64a4 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -6,6 +6,7 @@ generic-y += compat.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
+generic-y += dma-mapping.h
generic-y += emergency-restart.h
generic-y += extable.h
generic-y += fb.h
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
deleted file mode 100644
index 263f6acbfb0f..000000000000
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * DMA operations for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_DMA_MAPPING_H
-#define _ASM_DMA_MAPPING_H
-
-#include <linux/types.h>
-#include <linux/cache.h>
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-debug.h>
-#include <asm/io.h>
-
-struct device;
-
-extern const struct dma_map_ops *dma_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
-{
- return dma_ops;
-}
-
-#endif
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 9e46556a227d..ffc4ae8e126f 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -18,32 +18,19 @@
* 02110-1301, USA.
*/

-#include <linux/dma-mapping.h>
-#include <linux/dma-direct.h>
+#include <linux/dma-noncoherent.h>
#include <linux/bootmem.h>
#include <linux/genalloc.h>
-#include <asm/dma-mapping.h>
#include <linux/module.h>
#include <asm/page.h>

-#define HEXAGON_MAPPING_ERROR 0
-
-const struct dma_map_ops *dma_ops;
-EXPORT_SYMBOL(dma_ops);
-
-static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
-{
- return phys_to_virt((unsigned long) dma_addr);
-}
-
static struct gen_pool *coherent_pool;


/* Allocates from a pool of uncached memory that was reserved at boot time */

-static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addr, gfp_t flag,
- unsigned long attrs)
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_addr,
+ gfp_t flag, unsigned long attrs)
{
void *ret;

@@ -75,58 +62,17 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
return ret;
}

-static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr, unsigned long attrs)
+void arch_dma_free(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_addr, unsigned long attrs)
{
gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
}

-static int check_addr(const char *name, struct device *hwdev,
- dma_addr_t bus, size_t size)
-{
- if (hwdev && hwdev->dma_mask && !dma_capable(hwdev, bus, size)) {
- if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
- printk(KERN_ERR
- "%s: overflow %Lx+%zu of device mask %Lx\n",
- name, (long long)bus, size,
- (long long)*hwdev->dma_mask);
- return 0;
- }
- return 1;
-}
-
-static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir,
- unsigned long attrs)
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
+ size_t size, enum dma_data_direction dir)
{
- struct scatterlist *s;
- int i;
-
- WARN_ON(nents == 0 || sg[0].length == 0);
-
- for_each_sg(sg, s, nents, i) {
- s->dma_address = sg_phys(s);
- if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
- return 0;
-
- s->dma_length = s->length;
+ void *addr = phys_to_virt(paddr);

- if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
- continue;
-
- flush_dcache_range(dma_addr_to_virt(s->dma_address),
- dma_addr_to_virt(s->dma_address + s->length));
- }
-
- return nents;
-}
-
-/*
- * address is virtual
- */
-static inline void dma_sync(void *addr, size_t size,
- enum dma_data_direction dir)
-{
switch (dir) {
case DMA_TO_DEVICE:
hexagon_clean_dcache_range((unsigned long) addr,
@@ -144,81 +90,3 @@ static inline void dma_sync(void *addr, size_t size,
BUG();
}
}
-
-/**
- * hexagon_map_page() - maps an address for device DMA
- * @dev: pointer to DMA device
- * @page: pointer to page struct of DMA memory
- * @offset: offset within page
- * @size: size of memory to map
- * @dir: transfer direction
- * @attrs: pointer to DMA attrs (not used)
- *
- * Called to map a memory address to a DMA address prior
- * to accesses to/from device.
- *
- * We don't particularly have many hoops to jump through
- * so far. Straight translation between phys and virtual.
- *
- * DMA is not cache coherent so sync is necessary; this
- * seems to be a convenient place to do it.
- *
- */
-static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction dir,
- unsigned long attrs)
-{
- dma_addr_t bus = page_to_phys(page) + offset;
- WARN_ON(size == 0);
-
- if (!check_addr("map_single", dev, bus, size))
- return HEXAGON_MAPPING_ERROR;
-
- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
- dma_sync(dma_addr_to_virt(bus), size, dir);
-
- return bus;
-}
-
-static void hexagon_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir)
-{
- dma_sync(dma_addr_to_virt(dma_handle), size, dir);
-}
-
-static void hexagon_sync_sg_for_device(struct device *dev,
- struct scatterlist *sgl, int nents, enum dma_data_direction dir)
-{
- struct scatterlist *sg;
- int i;
-
- for_each_sg(sgl, sg, nents, i)
- hexagon_sync_single_for_device(dev, sg_dma_address(sg),
- sg->length, dir);
-}
-
-
-static int hexagon_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
- return dma_addr == HEXAGON_MAPPING_ERROR;
-}
-
-const struct dma_map_ops hexagon_dma_ops = {
- .alloc = hexagon_dma_alloc_coherent,
- .free = hexagon_free_coherent,
- .map_sg = hexagon_map_sg,
- .map_page = hexagon_map_page,
- .sync_single_for_device = hexagon_sync_single_for_device,
- .sync_sg_for_device = hexagon_sync_sg_for_device,
- .mapping_error = hexagon_mapping_error,
-};
-
-void __init hexagon_dma_init(void)
-{
- if (dma_ops)
- return;
-
- dma_ops = &hexagon_dma_ops;
-}
--
2.18.0


2018-07-19 12:58:30

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

hexagon does all the required cache maintainance at dma map time, and none
at unmap time. It thus has to implement sync_single_for_device to match
the map cace for buffer reuse, but there is no point in doing another
invalidation in the sync_single_cpu_case, which in terms of cache
maintainance is equivalent to the unmap case.

Signed-off-by: Christoph Hellwig <[email protected]>
---
arch/hexagon/kernel/dma.c | 8 --------
1 file changed, 8 deletions(-)

diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 77459df34e2e..d2b717f352f4 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -181,13 +181,6 @@ static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
return bus;
}

-static void hexagon_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir)
-{
- dma_sync(dma_addr_to_virt(dma_handle), size, dir);
-}
-
static void hexagon_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir)
@@ -205,7 +198,6 @@ const struct dma_map_ops hexagon_dma_ops = {
.free = hexagon_free_coherent,
.map_sg = hexagon_map_sg,
.map_page = hexagon_map_page,
- .sync_single_for_cpu = hexagon_sync_single_for_cpu,
.sync_single_for_device = hexagon_sync_single_for_device,
.mapping_error = hexagon_mapping_error,
};
--
2.18.0


2018-07-19 12:58:48

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 2/3] hexagon: implement the sync_sg_for_device DMA operation

This methods needs to provide the equivalent of sync_single_for_device
for each S/G list element, but was missing.

Signed-off-by: Christoph Hellwig <[email protected]>
---
arch/hexagon/kernel/dma.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index d2b717f352f4..9e46556a227d 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -188,6 +188,18 @@ static void hexagon_sync_single_for_device(struct device *dev,
dma_sync(dma_addr_to_virt(dma_handle), size, dir);
}

+static void hexagon_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sgl, int nents, enum dma_data_direction dir)
+{
+ struct scatterlist *sg;
+ int i;
+
+ for_each_sg(sgl, sg, nents, i)
+ hexagon_sync_single_for_device(dev, sg_dma_address(sg),
+ sg->length, dir);
+}
+
+
static int hexagon_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
return dma_addr == HEXAGON_MAPPING_ERROR;
@@ -199,6 +211,7 @@ const struct dma_map_ops hexagon_dma_ops = {
.map_sg = hexagon_map_sg,
.map_page = hexagon_map_page,
.sync_single_for_device = hexagon_sync_single_for_device,
+ .sync_sg_for_device = hexagon_sync_sg_for_device,
.mapping_error = hexagon_mapping_error,
};

--
2.18.0


2018-07-25 03:30:55

by Richard Kuo

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

On Thu, Jul 19, 2018 at 05:56:33AM -0700, Christoph Hellwig wrote:
> hexagon does all the required cache maintainance at dma map time, and none
> at unmap time. It thus has to implement sync_single_for_device to match
> the map cace for buffer reuse, but there is no point in doing another
> invalidation in the sync_single_cpu_case, which in terms of cache
> maintainance is equivalent to the unmap case.
>
> Signed-off-by: Christoph Hellwig <[email protected]>
> ---
> arch/hexagon/kernel/dma.c | 8 --------
> 1 file changed, 8 deletions(-)
>

Patch series looks good. Definitely appreciate the cleanup.

I can take it through my tree, or if not:

Acked-by: Richard Kuo <[email protected]>

Thanks!

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2018-07-25 04:36:58

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

On Tue, Jul 24, 2018 at 10:29:48PM -0500, Richard Kuo wrote:
> Patch series looks good. Definitely appreciate the cleanup.
>
> I can take it through my tree, or if not:
>
> Acked-by: Richard Kuo <[email protected]>

Please take it through your tree, thanks!

2018-07-31 15:19:40

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

On Wed, Jul 25, 2018 at 06:39:27AM +0200, Christoph Hellwig wrote:
> On Tue, Jul 24, 2018 at 10:29:48PM -0500, Richard Kuo wrote:
> > Patch series looks good. Definitely appreciate the cleanup.
> >
> > I can take it through my tree, or if not:
> >
> > Acked-by: Richard Kuo <[email protected]>
>
> Please take it through your tree, thanks!

I haven't seen it in linux-next yet, do you still plan to take it?

Otherwise I'll merge it in the dma-mapping tree.

2018-08-07 06:57:23

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

On Tue, Jul 31, 2018 at 05:22:29PM +0200, Christoph Hellwig wrote:
> On Wed, Jul 25, 2018 at 06:39:27AM +0200, Christoph Hellwig wrote:
> > On Tue, Jul 24, 2018 at 10:29:48PM -0500, Richard Kuo wrote:
> > > Patch series looks good. Definitely appreciate the cleanup.
> > >
> > > I can take it through my tree, or if not:
> > >
> > > Acked-by: Richard Kuo <[email protected]>
> >
> > Please take it through your tree, thanks!
>
> I haven't seen it in linux-next yet, do you still plan to take it?
>
> Otherwise I'll merge it in the dma-mapping tree.

Given that I haven't seen this in linux-next nor haven't heard back
from you I assume you are on your well deserved summer vacation.

If I don't hear back until tomorrow night I'll merge it through the
dma-mapping tree, so that I have it in linux-next before heading out
to my summer vacation.

2018-08-08 00:20:33

by Richard Kuo

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

On Tue, Aug 07, 2018 at 09:01:36AM +0200, Christoph Hellwig wrote:
> On Tue, Jul 31, 2018 at 05:22:29PM +0200, Christoph Hellwig wrote:
> > On Wed, Jul 25, 2018 at 06:39:27AM +0200, Christoph Hellwig wrote:
> > > On Tue, Jul 24, 2018 at 10:29:48PM -0500, Richard Kuo wrote:
> > > > Patch series looks good. Definitely appreciate the cleanup.
> > > >
> > > > I can take it through my tree, or if not:
> > > >
> > > > Acked-by: Richard Kuo <[email protected]>
> > >
> > > Please take it through your tree, thanks!
> >
> > I haven't seen it in linux-next yet, do you still plan to take it?
> >
> > Otherwise I'll merge it in the dma-mapping tree.
>
> Given that I haven't seen this in linux-next nor haven't heard back
> from you I assume you are on your well deserved summer vacation.
>
> If I don't hear back until tomorrow night I'll merge it through the
> dma-mapping tree, so that I have it in linux-next before heading out
> to my summer vacation.

I am here, and I have the patch queued up but it's waiting for approval
before I get to push it out through my tree.

That said, I am perfectly fine with this going through a different tree
if expedience is needed.


Thanks,
Richard Kuo


--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2018-08-08 06:15:19

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

On Tue, Aug 07, 2018 at 07:19:27PM -0500, Richard Kuo wrote:
> I am here, and I have the patch queued up but it's waiting for approval
> before I get to push it out through my tree.
>
> That said, I am perfectly fine with this going through a different tree
> if expedience is needed.

I just want to make sure it makes it for 4.19. In general going through
the arch maintainer tree is preferred, I just don't want to lose it.

2018-08-27 08:41:22

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 1/3] hexagon: remove the sync_single_for_cpu DMA operation

Given that it didn't make 4.19-rc1, I'll pull this into the dma-mapping
tree first thing for 4.20 as I have some other changes that will go on
top of it.