Configure flow control correctly, and based on the receive fifo size read as a property from the devicetree since the Synopsys stmmac fifo sizes are configurable based on a particular chip's implementation. This patch maintains the previous incorrect behavior unless the receive fifo size is found in the devicetree.
Signed-off-by: Vince Bridgers <vbrid...@opensource.altera.com> --- drivers/net/ethernet/stmicro/stmmac/common.h | 5 +++-- .../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 26 +++++++++++++++++++++- drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 ++++++++----- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index cd77289..623c6ed 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -150,7 +150,7 @@ struct stmmac_extra_stats { #define MAC_CSR_H_FRQ_MASK 0x20 #define HASH_TABLE_SIZE 64 -#define PAUSE_TIME 0x200 +#define PAUSE_TIME 0xffff /* Flow Control defines */ #define FLOW_OFF 0 @@ -357,7 +357,8 @@ struct stmmac_dma_ops { void (*dump_regs) (void __iomem *ioaddr); /* Set tx/rx threshold in the csr6 register * An invalid value enables the store-and-forward mode */ - void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode); + void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode, + int rxfifosz); /* To track extra statistic (if supported) */ void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, void __iomem *ioaddr); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 59d92e8..0e8937c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -106,8 +106,29 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, return 0; } +static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz) +{ + csr6 &= ~DMA_CONTROL_RFA_MASK; + csr6 &= ~DMA_CONTROL_RFD_MASK; + + /* Leave flow control disabled if receive fifo size is less than + * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full, + * and send XON when 2K less than full. + */ + if (rxfifosz < 4096) { + csr6 &= ~DMA_CONTROL_EFC; + pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n", + rxfifosz); + } else { + csr6 |= DMA_CONTROL_EFC; + csr6 |= RFA_FULL_MINUS_1K; + csr6 |= RFD_FULL_MINUS_2K; + } + return csr6; +} + static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, - int rxmode) + int rxmode, int rxfifosz) { u32 csr6 = readl(ioaddr + DMA_CONTROL); @@ -153,6 +174,9 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, csr6 |= DMA_CONTROL_RTC_128; } + /* Configure flow control based on rx fifo size */ + csr6 = dwmac1000_configure_fc(csr6, rxfifosz); + writel(csr6, ioaddr + DMA_CONTROL); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 7d1dce9..9d0971c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -72,7 +72,7 @@ static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, * control register. */ static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode, - int rxmode) + int rxmode, int rxfifosz) { u32 csr6 = readl(ioaddr + DMA_CONTROL); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a0ea84f..73d104f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1277,8 +1277,10 @@ static void free_dma_desc_resources(struct stmmac_priv *priv) */ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { + int rxfifosz = priv->plat->rx_fifo_size; + if (priv->plat->force_thresh_dma_mode) - priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); + priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { /* * In case of GMAC, SF mode can be enabled @@ -1287,10 +1289,12 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) * 2) There is no bugged Jumbo frame support * that needs to not insert csum in the TDES. */ - priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE); + priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE, + rxfifosz); priv->xstats.threshold = SF_DMA_MODE; } else - priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE); + priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE, + rxfifosz); } /** @@ -1442,6 +1446,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv) static void stmmac_dma_interrupt(struct stmmac_priv *priv) { int status; + int rxfifosz = priv->plat->rx_fifo_size; status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); if (likely((status & handle_rx)) || (status & handle_tx)) { @@ -1456,10 +1461,11 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) (tc <= 256)) { tc += 64; if (priv->plat->force_thresh_dma_mode) - priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); + priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, + rxfifosz); else priv->hw->dma->dma_mode(priv->ioaddr, tc, - SF_DMA_MODE); + SF_DMA_MODE, rxfifosz); priv->xstats.threshold = tc; } } else if (unlikely(status == tx_hard_error)) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/