aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMugunthan V N <mugunthanvnm@ti.com>2014-09-08 13:24:02 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-08 19:00:30 -0400
commit1923d6e4186c9470a83d0179e86e1aea8cfcbe67 (patch)
treefb299adcec814c969778592edf0c1b09339eaec8
parent119eccd5e7f6fcded9db6b7aa14f5f459d2a22ba (diff)
drivers: net: cpsw: Add support for pause frames
CPSW supports both rx and tx pause frames for flow control. Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ti/cpsw.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 03b409988566..76e73687d720 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -397,6 +397,8 @@ struct cpsw_priv {
397 struct cpdma_ctlr *dma; 397 struct cpdma_ctlr *dma;
398 struct cpdma_chan *txch, *rxch; 398 struct cpdma_chan *txch, *rxch;
399 struct cpsw_ale *ale; 399 struct cpsw_ale *ale;
400 bool rx_pause;
401 bool tx_pause;
400 /* snapshot of IRQ numbers */ 402 /* snapshot of IRQ numbers */
401 u32 irqs_table[4]; 403 u32 irqs_table[4];
402 u32 num_irqs; 404 u32 num_irqs;
@@ -832,6 +834,12 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
832 else if (phy->speed == 10) 834 else if (phy->speed == 10)
833 mac_control |= BIT(18); /* In Band mode */ 835 mac_control |= BIT(18); /* In Band mode */
834 836
837 if (priv->rx_pause)
838 mac_control |= BIT(3);
839
840 if (priv->tx_pause)
841 mac_control |= BIT(4);
842
835 *link = true; 843 *link = true;
836 } else { 844 } else {
837 mac_control = 0; 845 mac_control = 0;
@@ -1223,6 +1231,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
1223 /* enable statistics collection only on all ports */ 1231 /* enable statistics collection only on all ports */
1224 __raw_writel(0x7, &priv->regs->stat_port_en); 1232 __raw_writel(0x7, &priv->regs->stat_port_en);
1225 1233
1234 /* Enable internal fifo flow control */
1235 writel(0x7, &priv->regs->flow_control);
1236
1226 if (WARN_ON(!priv->data.rx_descs)) 1237 if (WARN_ON(!priv->data.rx_descs))
1227 priv->data.rx_descs = 128; 1238 priv->data.rx_descs = 128;
1228 1239
@@ -1784,6 +1795,30 @@ static int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
1784 return -EOPNOTSUPP; 1795 return -EOPNOTSUPP;
1785} 1796}
1786 1797
1798static void cpsw_get_pauseparam(struct net_device *ndev,
1799 struct ethtool_pauseparam *pause)
1800{
1801 struct cpsw_priv *priv = netdev_priv(ndev);
1802
1803 pause->autoneg = AUTONEG_DISABLE;
1804 pause->rx_pause = priv->rx_pause ? true : false;
1805 pause->tx_pause = priv->tx_pause ? true : false;
1806}
1807
1808static int cpsw_set_pauseparam(struct net_device *ndev,
1809 struct ethtool_pauseparam *pause)
1810{
1811 struct cpsw_priv *priv = netdev_priv(ndev);
1812 bool link;
1813
1814 priv->rx_pause = pause->rx_pause ? true : false;
1815 priv->tx_pause = pause->tx_pause ? true : false;
1816
1817 for_each_slave(priv, _cpsw_adjust_link, priv, &link);
1818
1819 return 0;
1820}
1821
1787static const struct ethtool_ops cpsw_ethtool_ops = { 1822static const struct ethtool_ops cpsw_ethtool_ops = {
1788 .get_drvinfo = cpsw_get_drvinfo, 1823 .get_drvinfo = cpsw_get_drvinfo,
1789 .get_msglevel = cpsw_get_msglevel, 1824 .get_msglevel = cpsw_get_msglevel,
@@ -1797,6 +1832,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
1797 .get_sset_count = cpsw_get_sset_count, 1832 .get_sset_count = cpsw_get_sset_count,
1798 .get_strings = cpsw_get_strings, 1833 .get_strings = cpsw_get_strings,
1799 .get_ethtool_stats = cpsw_get_ethtool_stats, 1834 .get_ethtool_stats = cpsw_get_ethtool_stats,
1835 .get_pauseparam = cpsw_get_pauseparam,
1836 .set_pauseparam = cpsw_set_pauseparam,
1800 .get_wol = cpsw_get_wol, 1837 .get_wol = cpsw_get_wol,
1801 .set_wol = cpsw_set_wol, 1838 .set_wol = cpsw_set_wol,
1802 .get_regs_len = cpsw_get_regs_len, 1839 .get_regs_len = cpsw_get_regs_len,