dma: mv_xor: big endian support
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
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
@@ -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
PATCH v2 2/2 mv_xor: support big endian systems using descriptor swap feature
In reply to Thomas PetazzoniThe 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
@@ -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
@@ -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
v2 cover dma: mv_xor: big endian support
In reply to Thomas PetazzoniVinod, 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_xordriver. 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:
* Usereadl_relaxed()andwritel_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 featuredrivers/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
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.
v2 cover dma: mv_xor: big endian support
In reply to Thomas PetazzoniQuoted 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_xordriver. 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:
* Usereadl_relaxed()andwritel_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 featuredrivers/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
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_xordriver. 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
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_xordriver. 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