The stmmac driver does not take into account the processor may be big
endian when writing the DMA descriptors. This causes the ethernet
interface not to be initialised correctly when running a big-endian
kernel. Change the descriptors for DMA to use __le32 and ensure they are
suitably swapped before writing. Tested successfully on the
Cubieboard2.
Signed-off-by: Michael Weiser
Cc: Giuseppe Cavallaro
Cc: Alexandre Torgue
Cc: netdev@vger.kernel.org
---
drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 55 ++--
drivers/net/ethernet/stmicro/stmmac/descs.h| 20
drivers/net/ethernet/stmicro/stmmac/descs_com.h| 48 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 60 +++---
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 55 ++--
drivers/net/ethernet/stmicro/stmmac/norm_desc.c| 48 -
drivers/net/ethernet/stmicro/stmmac/ring_mode.c| 39 +++---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 53 ++-
8 files changed, 196 insertions(+), 182 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index b3e669a..026e8e9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -34,7 +34,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int
csum)
unsigned int entry = priv->cur_tx;
struct dma_desc *desc = priv->dma_tx + entry;
unsigned int nopaged_len = skb_headlen(skb);
- unsigned int bmax;
+ unsigned int bmax, des2;
unsigned int i = 1, len;
if (priv->plat->enh_desc)
@@ -44,11 +44,12 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb,
int csum)
len = nopaged_len - bmax;
- desc->des2 = dma_map_single(priv->device, skb->data,
- bmax, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device, skb->data,
+ bmax, DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = bmax;
/* do not close the descriptor and do not set own bit */
priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
@@ -60,12 +61,13 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb,
int csum)
desc = priv->dma_tx + entry;
if (len > bmax) {
- desc->des2 = dma_map_single(priv->device,
- (skb->data + bmax * i),
- bmax, DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i),
+ bmax, DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = bmax;
priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
STMMAC_CHAIN_MODE, 1,
@@ -73,12 +75,13 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb,
int csum)
len -= bmax;
i++;
} else {
- desc->des2 = dma_map_single(priv->device,
- (skb->data + bmax * i), len,
- DMA_TO_DEVICE);
- if (dma_mapping_error(priv->device, desc->des2))
+ des2 = dma_map_single(priv->device,
+ (skb->data + bmax * i), len,
+ DMA_TO_DEVICE);
+ desc->des2 = cpu_to_le32(des2);
+ if (dma_mapping_error(priv->device, des2))
return -1;
- priv->tx_skbuff_dma[entry].buf = desc->des2;
+ priv->tx_skbuff_dma[entry].buf = des2;
priv->tx_skbuff_dma[entry].len = len;
/* last descriptor can be set now */
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
@@ -119,19 +122,19 @@ static void