diff options
| author | Vince Bridgers <vbridger@opensource.altera.com> | 2015-04-15 12:17:42 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-04-16 13:58:42 -0400 |
| commit | f88203a229cca0b3634738b7dae47419d1da6dc8 (patch) | |
| tree | d9bc05f136558819d3ca4ca67f2ef74798cdd743 /drivers/net/ethernet/stmicro | |
| parent | 545d655ebbea65986cb762905b81bff54f42eb6d (diff) | |
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>
Diffstat (limited to 'drivers/net/ethernet/stmicro')
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 26 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 2 | ||||
| -rw-r--r-- | 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 cd77289c3cfe..623c6ed8764a 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 { | |||
| 150 | #define MAC_CSR_H_FRQ_MASK 0x20 | 150 | #define MAC_CSR_H_FRQ_MASK 0x20 |
| 151 | 151 | ||
| 152 | #define HASH_TABLE_SIZE 64 | 152 | #define HASH_TABLE_SIZE 64 |
| 153 | #define PAUSE_TIME 0x200 | 153 | #define PAUSE_TIME 0xffff |
| 154 | 154 | ||
| 155 | /* Flow Control defines */ | 155 | /* Flow Control defines */ |
| 156 | #define FLOW_OFF 0 | 156 | #define FLOW_OFF 0 |
| @@ -357,7 +357,8 @@ struct stmmac_dma_ops { | |||
| 357 | void (*dump_regs) (void __iomem *ioaddr); | 357 | void (*dump_regs) (void __iomem *ioaddr); |
| 358 | /* Set tx/rx threshold in the csr6 register | 358 | /* Set tx/rx threshold in the csr6 register |
| 359 | * An invalid value enables the store-and-forward mode */ | 359 | * An invalid value enables the store-and-forward mode */ |
| 360 | void (*dma_mode) (void __iomem *ioaddr, int txmode, int rxmode); | 360 | void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode, |
| 361 | int rxfifosz); | ||
| 361 | /* To track extra statistic (if supported) */ | 362 | /* To track extra statistic (if supported) */ |
| 362 | void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, | 363 | void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, |
| 363 | void __iomem *ioaddr); | 364 | void __iomem *ioaddr); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 59d92e811750..0e8937c1184a 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, | |||
| 106 | return 0; | 106 | return 0; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz) | ||
| 110 | { | ||
| 111 | csr6 &= ~DMA_CONTROL_RFA_MASK; | ||
| 112 | csr6 &= ~DMA_CONTROL_RFD_MASK; | ||
| 113 | |||
| 114 | /* Leave flow control disabled if receive fifo size is less than | ||
| 115 | * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full, | ||
| 116 | * and send XON when 2K less than full. | ||
| 117 | */ | ||
| 118 | if (rxfifosz < 4096) { | ||
| 119 | csr6 &= ~DMA_CONTROL_EFC; | ||
| 120 | pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n", | ||
| 121 | rxfifosz); | ||
| 122 | } else { | ||
| 123 | csr6 |= DMA_CONTROL_EFC; | ||
| 124 | csr6 |= RFA_FULL_MINUS_1K; | ||
| 125 | csr6 |= RFD_FULL_MINUS_2K; | ||
| 126 | } | ||
| 127 | return csr6; | ||
| 128 | } | ||
| 129 | |||
| 109 | static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, | 130 | static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, |
| 110 | int rxmode) | 131 | int rxmode, int rxfifosz) |
| 111 | { | 132 | { |
| 112 | u32 csr6 = readl(ioaddr + DMA_CONTROL); | 133 | u32 csr6 = readl(ioaddr + DMA_CONTROL); |
| 113 | 134 | ||
| @@ -153,6 +174,9 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, | |||
| 153 | csr6 |= DMA_CONTROL_RTC_128; | 174 | csr6 |= DMA_CONTROL_RTC_128; |
| 154 | } | 175 | } |
| 155 | 176 | ||
| 177 | /* Configure flow control based on rx fifo size */ | ||
| 178 | csr6 = dwmac1000_configure_fc(csr6, rxfifosz); | ||
| 179 | |||
| 156 | writel(csr6, ioaddr + DMA_CONTROL); | 180 | writel(csr6, ioaddr + DMA_CONTROL); |
| 157 | } | 181 | } |
| 158 | 182 | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 7d1dce9e7ffc..9d0971c1c2ee 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, | |||
| 72 | * control register. | 72 | * control register. |
| 73 | */ | 73 | */ |
| 74 | static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode, | 74 | static void dwmac100_dma_operation_mode(void __iomem *ioaddr, int txmode, |
| 75 | int rxmode) | 75 | int rxmode, int rxfifosz) |
| 76 | { | 76 | { |
| 77 | u32 csr6 = readl(ioaddr + DMA_CONTROL); | 77 | u32 csr6 = readl(ioaddr + DMA_CONTROL); |
| 78 | 78 | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 60651738f2a9..05c146f718a3 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) | |||
| 1277 | */ | 1277 | */ |
| 1278 | static void stmmac_dma_operation_mode(struct stmmac_priv *priv) | 1278 | static void stmmac_dma_operation_mode(struct stmmac_priv *priv) |
| 1279 | { | 1279 | { |
| 1280 | int rxfifosz = priv->plat->rx_fifo_size; | ||
| 1281 | |||
| 1280 | if (priv->plat->force_thresh_dma_mode) | 1282 | if (priv->plat->force_thresh_dma_mode) |
| 1281 | priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); | 1283 | priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); |
| 1282 | else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { | 1284 | else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { |
| 1283 | /* | 1285 | /* |
| 1284 | * In case of GMAC, SF mode can be enabled | 1286 | * In case of GMAC, SF mode can be enabled |
| @@ -1287,10 +1289,12 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) | |||
| 1287 | * 2) There is no bugged Jumbo frame support | 1289 | * 2) There is no bugged Jumbo frame support |
| 1288 | * that needs to not insert csum in the TDES. | 1290 | * that needs to not insert csum in the TDES. |
| 1289 | */ | 1291 | */ |
| 1290 | priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE); | 1292 | priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE, |
| 1293 | rxfifosz); | ||
| 1291 | priv->xstats.threshold = SF_DMA_MODE; | 1294 | priv->xstats.threshold = SF_DMA_MODE; |
| 1292 | } else | 1295 | } else |
| 1293 | priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE); | 1296 | priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE, |
| 1297 | rxfifosz); | ||
| 1294 | } | 1298 | } |
| 1295 | 1299 | ||
| 1296 | /** | 1300 | /** |
| @@ -1442,6 +1446,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv) | |||
| 1442 | static void stmmac_dma_interrupt(struct stmmac_priv *priv) | 1446 | static void stmmac_dma_interrupt(struct stmmac_priv *priv) |
| 1443 | { | 1447 | { |
| 1444 | int status; | 1448 | int status; |
| 1449 | int rxfifosz = priv->plat->rx_fifo_size; | ||
| 1445 | 1450 | ||
| 1446 | status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); | 1451 | status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); |
| 1447 | if (likely((status & handle_rx)) || (status & handle_tx)) { | 1452 | if (likely((status & handle_rx)) || (status & handle_tx)) { |
| @@ -1456,10 +1461,11 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv) | |||
| 1456 | (tc <= 256)) { | 1461 | (tc <= 256)) { |
| 1457 | tc += 64; | 1462 | tc += 64; |
| 1458 | if (priv->plat->force_thresh_dma_mode) | 1463 | if (priv->plat->force_thresh_dma_mode) |
| 1459 | priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); | 1464 | priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, |
| 1465 | rxfifosz); | ||
| 1460 | else | 1466 | else |
| 1461 | priv->hw->dma->dma_mode(priv->ioaddr, tc, | 1467 | priv->hw->dma->dma_mode(priv->ioaddr, tc, |
| 1462 | SF_DMA_MODE); | 1468 | SF_DMA_MODE, rxfifosz); |
| 1463 | priv->xstats.threshold = tc; | 1469 | priv->xstats.threshold = tc; |
| 1464 | } | 1470 | } |
| 1465 | } else if (unlikely(status == tx_hard_error)) | 1471 | } else if (unlikely(status == tx_hard_error)) |
