Skip to content

Commit

Permalink
stmmac: Configure Flow Control to work correctly based on rxfifo size
Browse files Browse the repository at this point in the history
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 <vbridger@opensource.altera.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vince Bridgers authored and David S. Miller committed Apr 16, 2015
1 parent 545d655 commit f88203a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 9 deletions.
5 changes: 3 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
26 changes: 25 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
16 changes: 11 additions & 5 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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)) {
Expand All @@ -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))
Expand Down

0 comments on commit f88203a

Please sign in to comment.