Skip to contentSkip to conversation

dma: mv_xor: big endian support

PATCH Superseded Thomas Petazzoni 4 participants 8 messages Jul 29, 2013 – Aug 19, 2013 dmaengine

lore
Share & tools
lore
#0 lore raw

v2 cover dma: mv_xor: big endian support

Vinod, Dan,

This small set of patches adds support for big endian operation in the DMA mv_xor driver. It has been tested in both little-endian and big-endian modes on the Armada XP GP board.

If possible, I'd like those to be merged for 3.12.

Changes since v1:
* Use readl_relaxed() and writel_relaxed() instead of readl/writel when converting from raw_readl/raw_writel, since they preserve the same barrier behavior. Suggested by Russell King.

Thanks!

Thomas

Thomas Petazzoni (2):
mv_xor: use {readl,writel}_relaxed instead of __raw_{readl,writel}
mv_xor: support big endian systems using descriptor swap feature

 drivers/dma/mv_xor.c | 47 +++++++++++++++++++++++++++--------------------
 drivers/dma/mv_xor.h | 28 +++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 21 deletions(-)
Signature · 1 line
1.8.1.2
#1 lore raw

PATCH v2 1/2 mv_xor: use {readl, writel}_relaxed instead of __raw_{readl, writel}

In order to support big-endian execution, the mv_xor driver is changed to use the readl_relaxed() and writel_relaxed() accessors that properly convert from the CPU endianess to the device endianess (which in the case of Marvell XOR hardware is always little-endian).

---
 drivers/dma/mv_xor.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/dma/mv_xor.c +18 -18
index 200f1a3..c026b27 100644
@@ -114,25 +114,25 @@ static void mv_desc_set_src_addr(struct mv_xor_desc_slot *desc,
 
 static u32 mv_chan_get_current_desc(struct mv_xor_chan *chan)
 {
-	return __raw_readl(XOR_CURR_DESC(chan));
+	return readl_relaxed(XOR_CURR_DESC(chan));
 }
 
 static void mv_chan_set_next_descriptor(struct mv_xor_chan *chan,
 					u32 next_desc_addr)
 {
-	__raw_writel(next_desc_addr, XOR_NEXT_DESC(chan));
+	writel_relaxed(next_desc_addr, XOR_NEXT_DESC(chan));
 }
 
 static void mv_chan_unmask_interrupts(struct mv_xor_chan *chan)
 {
-	u32 val = __raw_readl(XOR_INTR_MASK(chan));
+	u32 val = readl_relaxed(XOR_INTR_MASK(chan));
 	val |= XOR_INTR_MASK_VALUE << (chan->idx * 16);
-	__raw_writel(val, XOR_INTR_MASK(chan));
+	writel_relaxed(val, XOR_INTR_MASK(chan));
 }
 
 static u32 mv_chan_get_intr_cause(struct mv_xor_chan *chan)
 {
-	u32 intr_cause = __raw_readl(XOR_INTR_CAUSE(chan));
+	u32 intr_cause = readl_relaxed(XOR_INTR_CAUSE(chan));
 	intr_cause = (intr_cause >> (chan->idx * 16)) & 0xFFFF;
 	return intr_cause;
 }
@@ -149,13 +149,13 @@ static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
 {
 	u32 val = ~(1 << (chan->idx * 16));
 	dev_dbg(mv_chan_to_devp(chan), "%s, val 0x%08x\n", __func__, val);
-	__raw_writel(val, XOR_INTR_CAUSE(chan));
+	writel_relaxed(val, XOR_INTR_CAUSE(chan));
 }
 
 static void mv_xor_device_clear_err_status(struct mv_xor_chan *chan)
 {
 	u32 val = 0xFFFF0000 >> (chan->idx * 16);
-	__raw_writel(val, XOR_INTR_CAUSE(chan));
+	writel_relaxed(val, XOR_INTR_CAUSE(chan));
 }
 
 static int mv_can_chain(struct mv_xor_desc_slot *desc)
@@ -173,7 +173,7 @@ static void mv_set_mode(struct mv_xor_chan *chan,
 			       enum dma_transaction_type type)
 {
 	u32 op_mode;
-	u32 config = __raw_readl(XOR_CONFIG(chan));
+	u32 config = readl_relaxed(XOR_CONFIG(chan));
 
 	switch (type) {
 	case DMA_XOR:
@@ -192,7 +192,7 @@ static void mv_set_mode(struct mv_xor_chan *chan,
 
 	config &= ~0x7;
 	config |= op_mode;
-	__raw_writel(config, XOR_CONFIG(chan));
+	writel_relaxed(config, XOR_CONFIG(chan));
 	chan->current_type = type;
 }
 
@@ -201,14 +201,14 @@ static void mv_chan_activate(struct mv_xor_chan *chan)
 	u32 activation;
 
 	dev_dbg(mv_chan_to_devp(chan), " activate chan.\n");
-	activation = __raw_readl(XOR_ACTIVATION(chan));
+	activation = readl_relaxed(XOR_ACTIVATION(chan));
 	activation |= 0x1;
-	__raw_writel(activation, XOR_ACTIVATION(chan));
+	writel_relaxed(activation, XOR_ACTIVATION(chan));
 }
 
 static char mv_chan_is_busy(struct mv_xor_chan *chan)
 {
-	u32 state = __raw_readl(XOR_ACTIVATION(chan));
+	u32 state = readl_relaxed(XOR_ACTIVATION(chan));
 
 	state = (state >> 4) & 0x3;
 
@@ -755,22 +755,22 @@ static void mv_dump_xor_regs(struct mv_xor_chan *chan)
 {
 	u32 val;
 
-	val = __raw_readl(XOR_CONFIG(chan));
+	val = readl_relaxed(XOR_CONFIG(chan));
 	dev_err(mv_chan_to_devp(chan), "config       0x%08x\n", val);
 
-	val = __raw_readl(XOR_ACTIVATION(chan));
+	val = readl_relaxed(XOR_ACTIVATION(chan));
 	dev_err(mv_chan_to_devp(chan), "activation   0x%08x\n", val);
 
-	val = __raw_readl(XOR_INTR_CAUSE(chan));
+	val = readl_relaxed(XOR_INTR_CAUSE(chan));
 	dev_err(mv_chan_to_devp(chan), "intr cause   0x%08x\n", val);
 
-	val = __raw_readl(XOR_INTR_MASK(chan));
+	val = readl_relaxed(XOR_INTR_MASK(chan));
 	dev_err(mv_chan_to_devp(chan), "intr mask    0x%08x\n", val);
 
-	val = __raw_readl(XOR_ERROR_CAUSE(chan));
+	val = readl_relaxed(XOR_ERROR_CAUSE(chan));
 	dev_err(mv_chan_to_devp(chan), "error cause  0x%08x\n", val);
 
-	val = __raw_readl(XOR_ERROR_ADDR(chan));
+	val = readl_relaxed(XOR_ERROR_ADDR(chan));
 	dev_err(mv_chan_to_devp(chan), "error addr   0x%08x\n", val);
 }
 
Signature · 1 line
1.8.1.2
#2 lore raw

PATCH v2 2/2 mv_xor: support big endian systems using descriptor swap feature

In reply to Thomas Petazzoni

The mv_xor driver had never been used in a big-endian context, and therefore was not using the hardware features to support such an execution environment. The hardware provides a "descriptor swap" bit that automatically swaps the bytes of the DMA descriptors, within blocks of 8 bytes. This requires a different DMA descriptor layout on big-endian systems, as well as enabling this "descriptor swap" bit.

This mechanism is exactly identical to the one already used in the mv643xx_eth network driver and the mvneta network driver.

---
 drivers/dma/mv_xor.c | 11 +++++++++--
 drivers/dma/mv_xor.h | 28 +++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 3 deletions(-)
drivers/dma/mv_xor.c +9 -2
index c026b27..d332b9e 100644
@@ -64,7 +64,7 @@ static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc,
 				int src_idx)
 {
 	struct mv_xor_desc *hw_desc = desc->hw_desc;
-	return hw_desc->phy_src_addr[src_idx];
+	return hw_desc->phy_src_addr[mv_phy_src_idx(src_idx)];
 }
 
 
@@ -107,7 +107,7 @@ static void mv_desc_set_src_addr(struct mv_xor_desc_slot *desc,
 				 int index, dma_addr_t addr)
 {
 	struct mv_xor_desc *hw_desc = desc->hw_desc;
-	hw_desc->phy_src_addr[index] = addr;
+	hw_desc->phy_src_addr[mv_phy_src_idx(index)] = addr;
 	if (desc->type == DMA_XOR)
 		hw_desc->desc_command |= (1 << index);
 }
@@ -192,6 +192,13 @@ static void mv_set_mode(struct mv_xor_chan *chan,
 
 	config &= ~0x7;
 	config |= op_mode;
+
+#if defined(__BIG_ENDIAN)
+	config |= XOR_DESCRIPTOR_SWAP;
+#else
+	config &= ~XOR_DESCRIPTOR_SWAP;
+#endif
+
 	writel_relaxed(config, XOR_CONFIG(chan));
 	chan->current_type = type;
 }
drivers/dma/mv_xor.h +27 -1
index c619359..06b067f 100644
@@ -29,8 +29,10 @@
 #define MV_XOR_THRESHOLD		1
 #define MV_XOR_MAX_CHANNELS             2
 
+/* Values for the XOR_CONFIG register */
 #define XOR_OPERATION_MODE_XOR		0
 #define XOR_OPERATION_MODE_MEMCPY	2
+#define XOR_DESCRIPTOR_SWAP		BIT(14)
 
 #define XOR_CURR_DESC(chan)	(chan->mmr_base + 0x210 + (chan->idx * 4))
 #define XOR_NEXT_DESC(chan)	(chan->mmr_base + 0x200 + (chan->idx * 4))
@@ -143,7 +145,16 @@ struct mv_xor_desc_slot {
 #endif
 };
 
-/* This structure describes XOR descriptor size 64bytes	*/
+/*
+ * This structure describes XOR descriptor size 64bytes. The
+ * mv_phy_src_idx() macro must be used when indexing the values of the
+ * phy_src_addr[] array. This is due to the fact that the 'descriptor
+ * swap' feature, used on big endian systems, swaps descriptors data
+ * within blocks of 8 bytes. So two consecutive values of the
+ * phy_src_addr[] array are actually swapped in big-endian, which
+ * explains the different mv_phy_src_idx() implementation.
+ */
+#if defined(__LITTLE_ENDIAN)
 struct mv_xor_desc {
 	u32 status;		/* descriptor execution status */
 	u32 crc32_result;	/* result of CRC-32 calculation */
@@ -155,6 +166,21 @@ struct mv_xor_desc {
 	u32 reserved0;
 	u32 reserved1;
 };
+#define mv_phy_src_idx(src_idx) (src_idx)
+#else
+struct mv_xor_desc {
+	u32 crc32_result;	/* result of CRC-32 calculation */
+	u32 status;		/* descriptor execution status */
+	u32 phy_next_desc;	/* next descriptor address pointer */
+	u32 desc_command;	/* type of operation to be carried out */
+	u32 phy_dest_addr;	/* destination block address */
+	u32 byte_count;		/* size of src/dst blocks in bytes */
+	u32 phy_src_addr[8];	/* source block addresses */
+	u32 reserved1;
+	u32 reserved0;
+};
+#define mv_phy_src_idx(src_idx) (src_idx ^ 1)
+#endif
 
 #define to_mv_sw_desc(addr_hw_desc)		\
 	container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc)
Signature · 1 line
1.8.1.2
#3 lore raw

v2 cover dma: mv_xor: big endian support

In reply to Thomas Petazzoni

Vinod, Dan,

I've sent the below two patches about three weeks ago, and they haven't received any comments. They are relatively simple, so would it be possible to queue them for 3.12 ?

Jason, Andrew, Gregory, as the Marvell EBU maintainers, it would be great if you could give your Acked-by and/or Tested-by on those patches.

Thanks!

Thomas

Quoted 25 lines · Thomas Petazzoni

Vinod, Dan,

This small set of patches adds support for big endian operation in the DMA mv_xor driver. It has been tested in both little-endian and big-endian modes on the Armada XP GP board.

If possible, I'd like those to be merged for 3.12.

Changes since v1:
* Use readl_relaxed() and writel_relaxed() instead of readl/writel when converting from raw_readl/raw_writel, since they preserve the same barrier behavior. Suggested by Russell King.

Thanks!

Thomas

Thomas Petazzoni (2):
mv_xor: use {readl,writel}_relaxed instead of __raw_{readl,writel}
mv_xor: support big endian systems using descriptor swap feature

 drivers/dma/mv_xor.c | 47 +++++++++++++++++++++++++++--------------------
 drivers/dma/mv_xor.h | 28 +++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 21 deletions(-)
Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#4 lore raw

v2 cover dma: mv_xor: big endian support

Quoted 2 lines · Thomas Petazzoni

Jason, Andrew, Gregory, as the Marvell EBU maintainers, it would be great if you could give your Acked-by and/or Tested-by on those patches.

Ahh, yes. I thought these had been accepted. If you're waiting for us,

thx,

Jason.

#5 lore raw

v2 cover dma: mv_xor: big endian support

In reply to Thomas Petazzoni
Quoted 6 lines · Thomas Petazzoni

Vinod, Dan,

I've sent the below two patches about three weeks ago, and they haven't received any comments. They are relatively simple, so would it be possible to queue them for 3.12 ?

Quoted 15 lines

Jason, Andrew, Gregory, as the Marvell EBU maintainers, it would be great if you could give your Acked-by and/or Tested-by on those patches.

Thanks!

Thomas

Quoted 7 lines · Thomas Petazzoni

Vinod, Dan,

This small set of patches adds support for big endian operation in the DMA mv_xor driver. It has been tested in both little-endian and big-endian modes on the Armada XP GP board.

If possible, I'd like those to be merged for 3.12.

These look fine to me.

Dan let me know if you okay with me to carry these

~Vinod

Quoted 26 lines
Quoted 18 lines

Changes since v1:
* Use readl_relaxed() and writel_relaxed() instead of readl/writel when converting from raw_readl/raw_writel, since they preserve the same barrier behavior. Suggested by Russell King.

Thanks!

Thomas

Thomas Petazzoni (2):
mv_xor: use {readl,writel}_relaxed instead of __raw_{readl,writel}
mv_xor: support big endian systems using descriptor swap feature

 drivers/dma/mv_xor.c | 47 +++++++++++++++++++++++++++--------------------
 drivers/dma/mv_xor.h | 28 +++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 21 deletions(-)
Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#6 lore raw

v2 cover dma: mv_xor: big endian support

Quoted 17 lines · Vinod Koul
Quoted 16 lines · Thomas Petazzoni

Vinod, Dan,

I've sent the below two patches about three weeks ago, and they haven't received any comments. They are relatively simple, so would it be possible to queue them for 3.12 ?

Jason, Andrew, Gregory, as the Marvell EBU maintainers, it would be great if you could give your Acked-by and/or Tested-by on those patches.

Thanks!

Thomas

Quoted 2 lines · Thomas Petazzoni

Vinod, Dan,

Quoted 8 lines
Quoted 5 lines
Quoted 5 lines

This small set of patches adds support for big endian operation in the DMA mv_xor driver. It has been tested in both little-endian and big-endian modes on the Armada XP GP board.

If possible, I'd like those to be merged for 3.12.

These look fine to me.

Dan let me know if you okay with me to carry these

I'm dusting off the tree for a few other patches. I'll apply them.

--
Dan

#7 lore raw

v2 cover dma: mv_xor: big endian support

Dear Dan Williams,

Quoted 6 lines · Dan Williams
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Vinod, Dan,

This small set of patches adds support for big endian operation in the DMA mv_xor driver. It has been tested in both little-endian and big-endian modes on the Armada XP GP board.

Quoted 6 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line

If possible, I'd like those to be merged for 3.12.

These look fine to me.

Dan let me know if you okay with me to carry these

I'm dusting off the tree for a few other patches. I'll apply them.

Great, thanks!

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com