mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
stmmac: Configure Flow Control to work correctly based on rxfifo size
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>
This commit is contained in:
parent
545d655ebb
commit
f88203a229
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user