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)) |