mirror of https://gitee.com/openkylin/linux.git
mv_xor: support big endian systems using descriptor swap feature
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. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Dan Williams <djbw@fb.com>
This commit is contained in:
parent
5733c38ae3
commit
e03bc654f8
|
@ -64,7 +64,7 @@ static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc,
|
||||||
int src_idx)
|
int src_idx)
|
||||||
{
|
{
|
||||||
struct mv_xor_desc *hw_desc = desc->hw_desc;
|
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)
|
int index, dma_addr_t addr)
|
||||||
{
|
{
|
||||||
struct mv_xor_desc *hw_desc = desc->hw_desc;
|
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)
|
if (desc->type == DMA_XOR)
|
||||||
hw_desc->desc_command |= (1 << index);
|
hw_desc->desc_command |= (1 << index);
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,13 @@ static void mv_set_mode(struct mv_xor_chan *chan,
|
||||||
|
|
||||||
config &= ~0x7;
|
config &= ~0x7;
|
||||||
config |= op_mode;
|
config |= op_mode;
|
||||||
|
|
||||||
|
#if defined(__BIG_ENDIAN)
|
||||||
|
config |= XOR_DESCRIPTOR_SWAP;
|
||||||
|
#else
|
||||||
|
config &= ~XOR_DESCRIPTOR_SWAP;
|
||||||
|
#endif
|
||||||
|
|
||||||
writel_relaxed(config, XOR_CONFIG(chan));
|
writel_relaxed(config, XOR_CONFIG(chan));
|
||||||
chan->current_type = type;
|
chan->current_type = type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@
|
||||||
#define MV_XOR_THRESHOLD 1
|
#define MV_XOR_THRESHOLD 1
|
||||||
#define MV_XOR_MAX_CHANNELS 2
|
#define MV_XOR_MAX_CHANNELS 2
|
||||||
|
|
||||||
|
/* Values for the XOR_CONFIG register */
|
||||||
#define XOR_OPERATION_MODE_XOR 0
|
#define XOR_OPERATION_MODE_XOR 0
|
||||||
#define XOR_OPERATION_MODE_MEMCPY 2
|
#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_CURR_DESC(chan) (chan->mmr_base + 0x210 + (chan->idx * 4))
|
||||||
#define XOR_NEXT_DESC(chan) (chan->mmr_base + 0x200 + (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
|
#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 {
|
struct mv_xor_desc {
|
||||||
u32 status; /* descriptor execution status */
|
u32 status; /* descriptor execution status */
|
||||||
u32 crc32_result; /* result of CRC-32 calculation */
|
u32 crc32_result; /* result of CRC-32 calculation */
|
||||||
|
@ -155,6 +166,21 @@ struct mv_xor_desc {
|
||||||
u32 reserved0;
|
u32 reserved0;
|
||||||
u32 reserved1;
|
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) \
|
#define to_mv_sw_desc(addr_hw_desc) \
|
||||||
container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc)
|
container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc)
|
||||||
|
|
Loading…
Reference in New Issue