Re: [PATCH v8 1/3] dmaengine: fsl-edma: extract common fsl-edma code (no changes in behavior intended)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10.08.2018 00:37, Angelo Dureghello wrote:
Hi Stefan,

i am about to post a v9 in short.

On Tue, Aug 07, 2018 at 07:47:19PM +0200, Stefan Agner wrote:
On 07.08.2018 14:14, Krzysztof Kozlowski wrote:
On 7 August 2018 at 10:08, Stefan Agner <stefan@xxxxxxxx> wrote:
On 03.08.2018 21:32, Angelo Dureghello wrote:
This patch adds a new fsl-edma-common module to allow new
mcf-edma module code to use most of the fsl-edma code.

Signed-off-by: Angelo Dureghello <angelo@xxxxxxxx>
---
Changes for v2:
- patch splitted into 4
- add mcf-edma as minimal different parts from fsl-edma

Changes for v3:
none

Changes for v4:
- patch simplified from 4/4 into 2/2
- collecting all the mcf-edma-related changes

Changes for v5:
none

Changes for v6:
- adjusted comment header
- fixed bit shift with BIT()
- we need to free the interrupts at remove(), so removed all devm_
  interrupt related calls

Changes for v7:
none

Changes for v8:
- patch rewritten from scratch, splitted into 3, common code isolated,
  minimal changes from the original Freescale code have been done.
  The patch has been tested with both Iris + Colibri Vybrid VF50 and
  stmark2/mcf54415 Coldfire boards.
---
 drivers/dma/Makefile          |   2 +-
 drivers/dma/fsl-edma-common.c | 576 ++++++++++++++++++++++++++++
 drivers/dma/fsl-edma-common.h | 196 ++++++++++
 drivers/dma/fsl-edma.c        | 697 +---------------------------------
 4 files changed, 774 insertions(+), 697 deletions(-)
 create mode 100644 drivers/dma/fsl-edma-common.c
 create mode 100644 drivers/dma/fsl-edma-common.h

diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 203a99d68315..66022f59fca4 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -31,7 +31,7 @@ obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/
 obj-$(CONFIG_DW_DMAC_CORE) += dw/
 obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
-obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
+obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o
 obj-$(CONFIG_FSL_RAID) += fsl_raid.o
 obj-$(CONFIG_HSU_DMA) += hsu/
 obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
new file mode 100644
index 000000000000..0ae7094f477a
--- /dev/null
+++ b/drivers/dma/fsl-edma-common.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
+// Copyright (c) 2017 Sysam, Angelo Dureghello  <angelo@xxxxxxxx>
+
+#include <linux/dmapool.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "fsl-edma-common.h"
+
+/*
+ * R/W functions for big- or little-endian registers:
+ * The eDMA controller's endian is independent of the CPU core's endian.
+ * For the big-endian IP module, the offset for 8-bit or 16-bit registers
+ * should also be swapped opposite to that in little-endian IP.
+ */
+u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
+{
+     if (edma->big_endian)
+             return ioread32be(addr);
+     else
+             return ioread32(addr);
+}
+EXPORT_SYMBOL_GPL(edma_readl);

In 3/3 you link the common object into the two modules individually:

obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o
obj-$(CONFIG_MCF_EDMA) += mcf-edma.o fsl-edma-common.o

Therefor you do not access those functions from another module (they are
within the module). No exporting should be necessary. Drop all those
exports.

The fsl-edma-common will be its own module so the exports are
necessary for proper linking/modpost.

Hm, oh I see, I got that wrong.

We could use
fsl-edma-all-y = fsl-edma.o fsl-edma-common.o
obj-$(CONFIG_FSL_EDMA) += fsl-edma-all.o
mcf-edma-all-y = mcf-edma.o fsl-edma-common.o
obj-$(CONFIG_MCF_EDMA) += mcf-edma-all.o

to create two modules but that duplicates some code. It probably
wouldn't matter in practise since the two IPs are used on different
architecture...

However, if we stay with the three modules approach, we should introduce
a hidden config symbol, e.g.

config FSL_EDMA_COMMON
	tristate

In FSL_EDMA/MCF_EDMA use
	select FSL_EDMA_COMMON

And in the Makefile
obj-$(CONFIG_FSL_EDMA_COMMON) += fsl-edma-common.o
obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
obj-$(CONFIG_MCF_EDMA) += mcf-edma.o


There was already a discussion with Vinod and Geert on this, and i 
finally previously changed things in this way 

obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o

The idea was to simplify things avoiding to use an additional
config symbol, as i did initially. It's a common pattern in 
several Makefiles (e.g.drivers/net/ethernet/8390/Makefile and 
drivers/scsi/Makefile).
Also we have a single common code part since obj-y is a list, 
and IIRC it's filtered for duplicates.
So if can be ok for you too, i would not roll back again.


I see, you refer to this discussion:
https://www.spinics.net/lists/dmaengine/msg15863.html

Should have followed up on those discussions, sorry. Leave it as is
then.

However, I do not like that the compiler can no longer inline simple
acesors like edma_(readl|writel). So if we stay with the three modules
approach then move at least the accesors and
to_fsl_edma_chan/to_fsl_edma_desc as inline functions to the header
file.

I agree too, my initial patch was a single separate driver. But it
resulted in too much duplicated code, so a common module has been
required. Btw, seems i cannot inline those functions. fsl-edma-common.h 
is included from both fsl-edma-common.c and mcf/fsl-edma.c resulting
in multiple definitions linking error.

I agree, we should introduce the common module and share as much as
possible.

Just those small accessors typically get inlined by the compiler, and
often collapse completely in optimization phases (e.g. a function call
has more overhead than just inlining them, making resulting code smaller
and faster).

Just define them as static inline, then it won't lead to linking errors.

I tried with this change in fsl-edma-common.h (and remove them from
fsl-edma-common.c):

-u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr);
-void edma_writeb(struct fsl_edma_engine *edma, u8 val, void __iomem
*addr);
-void edma_writew(struct fsl_edma_engine *edma, u16 val, void __iomem
*addr);
-void edma_writel(struct fsl_edma_engine *edma, u32 val, void __iomem
*addr);
-
-struct fsl_edma_chan *to_fsl_edma_chan(struct dma_chan *chan);
-struct fsl_edma_desc *to_fsl_edma_desc(struct virt_dma_desc *vd);
+/*
+ * R/W functions for big- or little-endian registers:
+ * The eDMA controller's endian is independent of the CPU core's
endian.
+ * For the big-endian IP module, the offset for 8-bit or 16-bit
registers
+ * should also be swapped opposite to that in little-endian IP.
+ */
+static inline u32 edma_readl(struct fsl_edma_engine *edma, void __iomem
*addr)
+{
+       if (edma->big_endian)
+               return ioread32be(addr);
+       else
+               return ioread32(addr);
+}
+
+static inline void edma_writeb(struct fsl_edma_engine *edma, u8 val,
void __iomem *addr)
+{
+       /* swap the reg offset for these in big-endian mode */
+       if (edma->big_endian)
+               iowrite8(val, (void __iomem *)((unsigned long)addr ^
0x3));
+       else
+               iowrite8(val, addr);
+}
+
+static inline void edma_writew(struct fsl_edma_engine *edma, u16 val,
void __iomem *addr)
+{
+       /* swap the reg offset for these in big-endian mode */
+       if (edma->big_endian)
+               iowrite16be(val, (void __iomem *)((unsigned long)addr ^
0x2));
+       else
+               iowrite16(val, addr);
+}
+
+static inline void edma_writel(struct fsl_edma_engine *edma, u32 val,
void __iomem *addr)
+{
+       if (edma->big_endian)
+               iowrite32be(val, addr);
+       else
+               iowrite32(val, addr);
+}
+
+static inline struct fsl_edma_chan *to_fsl_edma_chan(struct dma_chan
*chan)
+{
+       return container_of(chan, struct fsl_edma_chan, vchan.chan);
+}
+
+static inline struct fsl_edma_desc *to_fsl_edma_desc(struct
virt_dma_desc *vd)
+{
+       return container_of(vd, struct fsl_edma_desc, vdesc);
+}


All three kernel modules end up being smaller (overall more than 1kB),
so the compiler really does its magic.


Mainly until v7 there was several discussions and a first approval, 
if possible i would not change again heavily the patch structure for
a bug that seemss already been fixed.

So i fixed all the possible points of this thread and organized next 
patch as 

1/4 dmaengine: fsl-edma: extract common fsl-edma code (no changes ..
2/4 dmaengine: fsl-edma: add edma version and configurable registers
3/4 dmaengine: fsl-edma: fix macros
4/4 dmaengine: fsl-edma: add ColdFire mcf5441x edma support

That seems sensible. One minor nit in Kconfig still:

--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -320,6 +320,17 @@ config LPC18XX_DMAMUX
       Enable support for DMA on NXP LPC18xx/43xx platforms
       with PL080 and multiplexed DMA request lines.
 
+config MCF_EDMA
+    tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
+    depends on M5441x

Can you add " || COMPILE_TEST" here, this helps for automated testing.

--
Stefan


Let me know if you have any other point or if can proceed.

Best regards,
Angelo Dureghello

--
Stefan


Best regards,
Krzysztof

If possible I would prefer if you start with cleanup/conversions, then
split-up and finally add functionality.

So ideally:
1. Use macros for preprocessor defines (where you move to BIT/GENMASK)
2. Split
3. Add EDMA macros etc.
4. Add ColdFire mcf5441x edma support

--
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux