forked from Minki/linux
net: mv643xx_eth: Ensure proper data alignment in TSO TX path
The TX DMA engine requires that buffers with a size of 8 bytes or smaller must be 64 bit aligned. This requirement may be violated when doing TSO, as in this case larger skb frags can be broken up and transmitted in small parts with then inappropriate alignment. Fix this by checking for proper alignment before handing a buffer to the DMA engine. If the data is misaligned realign it by copying it into the TSO header data area. Signed-off-by: Philipp Kirchhofer <philipp@familie-kirchhofer.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f3c9f95056
commit
91986fd3d3
@ -759,11 +759,23 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
|
||||
|
||||
desc->l4i_chk = 0;
|
||||
desc->byte_cnt = length;
|
||||
desc->buf_ptr = dma_map_single(dev->dev.parent, data,
|
||||
length, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) {
|
||||
WARN(1, "dma_map_single failed!\n");
|
||||
return -ENOMEM;
|
||||
|
||||
if (length <= 8 && (uintptr_t)data & 0x7) {
|
||||
/* Copy unaligned small data fragment to TSO header data area */
|
||||
memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE,
|
||||
data, length);
|
||||
desc->buf_ptr = txq->tso_hdrs_dma
|
||||
+ txq->tx_curr_desc * TSO_HEADER_SIZE;
|
||||
} else {
|
||||
/* Alignment is okay, map buffer and hand off to hardware */
|
||||
txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
|
||||
desc->buf_ptr = dma_map_single(dev->dev.parent, data,
|
||||
length, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dev.parent,
|
||||
desc->buf_ptr))) {
|
||||
WARN(1, "dma_map_single failed!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_sts = BUFFER_OWNED_BY_DMA;
|
||||
|
Loading…
Reference in New Issue
Block a user