aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorFrank Li <Frank.Li@freescale.com>2013-01-16 11:55:58 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-18 14:16:11 -0500
commitbaa70a5c48a01ea02e32270eb96eb19bd3b76667 (patch)
tree723639105a31fa1abb31261e17108b38cdd85178 /drivers/net/ethernet
parent8b5b6f5413e97c3e8bafcdd67553d508f4f698cd (diff)
net: fec: enable pause frame to improve rx prefomance for 1G network
The limition of imx6 internal bus cause fec can't achieve 1G perfomance. There will be many packages lost because FIFO over run. This patch enable pause frame flow control. Before this patch iperf -s -i 1 TCP window size: 85.3 KByte (default) ------------------------------------------------------------ [ 4] local 10.192.242.153 port 5001 connected with 10.192.242.94 port 49773 [ ID] Interval Transfer Bandwidth [ 4] 0.0- 1.0 sec 6.35 MBytes 53.3 Mbits/sec [ 4] 1.0- 2.0 sec 3.39 MBytes 28.5 Mbits/sec [ 4] 2.0- 3.0 sec 2.63 MBytes 22.1 Mbits/sec [ 4] 3.0- 4.0 sec 1.10 MBytes 9.23 Mbits/sec ifconfig RX packets:46195 errors:1859 dropped:1 overruns:1859 frame:1859 After this patch iperf -s -i 1 [ 4] local 10.192.242.153 port 5001 connected with 10.192.242.94 port 49757 [ ID] Interval Transfer Bandwidth [ 4] 0.0- 1.0 sec 49.8 MBytes 418 Mbits/sec [ 4] 1.0- 2.0 sec 50.1 MBytes 420 Mbits/sec [ 4] 2.0- 3.0 sec 47.5 MBytes 399 Mbits/sec [ 4] 3.0- 4.0 sec 45.9 MBytes 385 Mbits/sec [ 4] 4.0- 5.0 sec 44.8 MBytes 376 Mbits/sec ifconfig RX packets:2348454 errors:0 dropped:16 overruns:0 frame:0 Signed-off-by: Frank Li <Frank.Li@freescale.com> Signed-off-by: Fugang Duan <B38611@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/freescale/fec.c87
-rw-r--r--drivers/net/ethernet/freescale/fec.h5
2 files changed, 91 insertions, 1 deletions
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 1b7684a8851e..f52ba338d2c7 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -68,6 +68,14 @@
68 68
69#define DRIVER_NAME "fec" 69#define DRIVER_NAME "fec"
70 70
71/* Pause frame feild and FIFO threshold */
72#define FEC_ENET_FCE (1 << 5)
73#define FEC_ENET_RSEM_V 0x84
74#define FEC_ENET_RSFL_V 16
75#define FEC_ENET_RAEM_V 0x8
76#define FEC_ENET_RAFL_V 0x8
77#define FEC_ENET_OPD_V 0xFFF0
78
71/* Controller is ENET-MAC */ 79/* Controller is ENET-MAC */
72#define FEC_QUIRK_ENET_MAC (1 << 0) 80#define FEC_QUIRK_ENET_MAC (1 << 0)
73/* Controller needs driver to swap frame */ 81/* Controller needs driver to swap frame */
@@ -193,6 +201,9 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
193/* Transmitter timeout */ 201/* Transmitter timeout */
194#define TX_TIMEOUT (2 * HZ) 202#define TX_TIMEOUT (2 * HZ)
195 203
204#define FEC_PAUSE_FLAG_AUTONEG 0x1
205#define FEC_PAUSE_FLAG_ENABLE 0x2
206
196static int mii_cnt; 207static int mii_cnt;
197 208
198static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex) 209static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, int is_ex)
@@ -470,6 +481,25 @@ fec_restart(struct net_device *ndev, int duplex)
470 } 481 }
471#endif 482#endif
472 } 483 }
484
485 /* enable pause frame*/
486 if ((fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) ||
487 ((fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) &&
488 fep->phy_dev && fep->phy_dev->pause)) {
489 rcntl |= FEC_ENET_FCE;
490
491 /* set FIFO thresh hold parameter to reduce overrun */
492 writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
493 writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
494 writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
495 writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL);
496
497 /* OPD */
498 writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD);
499 } else {
500 rcntl &= ~FEC_ENET_FCE;
501 }
502
473 writel(rcntl, fep->hwp + FEC_R_CNTRL); 503 writel(rcntl, fep->hwp + FEC_R_CNTRL);
474 504
475 if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { 505 if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
@@ -1016,8 +1046,10 @@ static int fec_enet_mii_probe(struct net_device *ndev)
1016 } 1046 }
1017 1047
1018 /* mask with MAC supported features */ 1048 /* mask with MAC supported features */
1019 if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) 1049 if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
1020 phy_dev->supported &= PHY_GBIT_FEATURES; 1050 phy_dev->supported &= PHY_GBIT_FEATURES;
1051 phy_dev->supported |= SUPPORTED_Pause;
1052 }
1021 else 1053 else
1022 phy_dev->supported &= PHY_BASIC_FEATURES; 1054 phy_dev->supported &= PHY_BASIC_FEATURES;
1023 1055
@@ -1203,7 +1235,55 @@ static int fec_enet_get_ts_info(struct net_device *ndev,
1203 } 1235 }
1204} 1236}
1205 1237
1238static void fec_enet_get_pauseparam(struct net_device *ndev,
1239 struct ethtool_pauseparam *pause)
1240{
1241 struct fec_enet_private *fep = netdev_priv(ndev);
1242
1243 pause->autoneg = (fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) != 0;
1244 pause->tx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) != 0;
1245 pause->rx_pause = pause->tx_pause;
1246}
1247
1248static int fec_enet_set_pauseparam(struct net_device *ndev,
1249 struct ethtool_pauseparam *pause)
1250{
1251 struct fec_enet_private *fep = netdev_priv(ndev);
1252
1253 if (pause->tx_pause != pause->rx_pause) {
1254 netdev_info(ndev,
1255 "hardware only support enable/disable both tx and rx");
1256 return -EINVAL;
1257 }
1258
1259 fep->pause_flag = 0;
1260
1261 /* tx pause must be same as rx pause */
1262 fep->pause_flag |= pause->rx_pause ? FEC_PAUSE_FLAG_ENABLE : 0;
1263 fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0;
1264
1265 if (pause->rx_pause || pause->autoneg) {
1266 fep->phy_dev->supported |= ADVERTISED_Pause;
1267 fep->phy_dev->advertising |= ADVERTISED_Pause;
1268 } else {
1269 fep->phy_dev->supported &= ~ADVERTISED_Pause;
1270 fep->phy_dev->advertising &= ~ADVERTISED_Pause;
1271 }
1272
1273 if (pause->autoneg) {
1274 if (netif_running(ndev))
1275 fec_stop(ndev);
1276 phy_start_aneg(fep->phy_dev);
1277 }
1278 if (netif_running(ndev))
1279 fec_restart(ndev, 0);
1280
1281 return 0;
1282}
1283
1206static const struct ethtool_ops fec_enet_ethtool_ops = { 1284static const struct ethtool_ops fec_enet_ethtool_ops = {
1285 .get_pauseparam = fec_enet_get_pauseparam,
1286 .set_pauseparam = fec_enet_set_pauseparam,
1207 .get_settings = fec_enet_get_settings, 1287 .get_settings = fec_enet_get_settings,
1208 .set_settings = fec_enet_set_settings, 1288 .set_settings = fec_enet_set_settings,
1209 .get_drvinfo = fec_enet_get_drvinfo, 1289 .get_drvinfo = fec_enet_get_drvinfo,
@@ -1643,6 +1723,11 @@ fec_probe(struct platform_device *pdev)
1643 /* setup board info structure */ 1723 /* setup board info structure */
1644 fep = netdev_priv(ndev); 1724 fep = netdev_priv(ndev);
1645 1725
1726 /* default enable pause frame auto negotiation */
1727 if (pdev->id_entry &&
1728 (pdev->id_entry->driver_data & FEC_QUIRK_HAS_GBIT))
1729 fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
1730
1646 fep->hwp = ioremap(r->start, resource_size(r)); 1731 fep->hwp = ioremap(r->start, resource_size(r));
1647 fep->pdev = pdev; 1732 fep->pdev = pdev;
1648 fep->dev_id = dev_id++; 1733 fep->dev_id = dev_id++;
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 48623947d956..2ebedaf7ad81 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -48,6 +48,10 @@
48#define FEC_R_DES_START 0x180 /* Receive descriptor ring */ 48#define FEC_R_DES_START 0x180 /* Receive descriptor ring */
49#define FEC_X_DES_START 0x184 /* Transmit descriptor ring */ 49#define FEC_X_DES_START 0x184 /* Transmit descriptor ring */
50#define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ 50#define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */
51#define FEC_R_FIFO_RSFL 0x190 /* Receive FIFO section full threshold */
52#define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */
53#define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */
54#define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */
51#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */ 55#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */
52#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */ 56#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */
53 57
@@ -243,6 +247,7 @@ struct fec_enet_private {
243 struct completion mdio_done; 247 struct completion mdio_done;
244 int irq[FEC_IRQ_NUM]; 248 int irq[FEC_IRQ_NUM];
245 int bufdesc_ex; 249 int bufdesc_ex;
250 int pause_flag;
246 251
247 struct ptp_clock *ptp_clock; 252 struct ptp_clock *ptp_clock;
248 struct ptp_clock_info ptp_caps; 253 struct ptp_clock_info ptp_caps;