diff options
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_xgess.c')
-rw-r--r-- | drivers/net/ethernet/ti/keystone_xgess.c | 88 |
1 files changed, 56 insertions, 32 deletions
diff --git a/drivers/net/ethernet/ti/keystone_xgess.c b/drivers/net/ethernet/ti/keystone_xgess.c index a09de9044d2..a84d5d78623 100644 --- a/drivers/net/ethernet/ti/keystone_xgess.c +++ b/drivers/net/ethernet/ti/keystone_xgess.c | |||
@@ -69,6 +69,11 @@ | |||
69 | (MACSL_XGMII_ENABLE | MACSL_XGIG_MODE) : \ | 69 | (MACSL_XGMII_ENABLE | MACSL_XGIG_MODE) : \ |
70 | MACSL_GMII_ENABLE) | 70 | MACSL_GMII_ENABLE) |
71 | 71 | ||
72 | #define MACSL_DEFAULT_CONFIG(s) \ | ||
73 | (MACSL_SIG_ENABLE((s)) | \ | ||
74 | MACSL_RX_ENABLE_EXT_CTL | \ | ||
75 | MACSL_RX_ENABLE_CSF) | ||
76 | |||
72 | #define CPSW_NUM_PORTS 3 | 77 | #define CPSW_NUM_PORTS 3 |
73 | #define CPSW_CTL_P0_ENABLE BIT(2) | 78 | #define CPSW_CTL_P0_ENABLE BIT(2) |
74 | #define CPSW_CTL_VLAN_AWARE BIT(1) | 79 | #define CPSW_CTL_VLAN_AWARE BIT(1) |
@@ -85,6 +90,9 @@ | |||
85 | #define HOST_TX_PRI_MAP_DEFAULT 0x00000000 | 90 | #define HOST_TX_PRI_MAP_DEFAULT 0x00000000 |
86 | #define MAX_SIZE_STREAM_BUFFER 9504 | 91 | #define MAX_SIZE_STREAM_BUFFER 9504 |
87 | 92 | ||
93 | /* slave_num: 0-based | ||
94 | * port_num: 1-based | ||
95 | */ | ||
88 | struct cpswx_slave { | 96 | struct cpswx_slave { |
89 | struct cpswx_slave_regs __iomem *regs; | 97 | struct cpswx_slave_regs __iomem *regs; |
90 | struct cpswx_sliver_regs __iomem *sliver; | 98 | struct cpswx_sliver_regs __iomem *sliver; |
@@ -301,8 +309,11 @@ struct cpswx_priv { | |||
301 | struct kobject stats_kobj; | 309 | struct kobject stats_kobj; |
302 | spinlock_t hw_stats_lock; | 310 | spinlock_t hw_stats_lock; |
303 | struct device_node *serdes; | 311 | struct device_node *serdes; |
312 | u32 opened; | ||
304 | }; | 313 | }; |
305 | 314 | ||
315 | /* slave_port: 0-based (currently relevant only in multi_if mode) | ||
316 | */ | ||
306 | struct cpswx_intf { | 317 | struct cpswx_intf { |
307 | struct net_device *ndev; | 318 | struct net_device *ndev; |
308 | struct device *dev; | 319 | struct device *dev; |
@@ -318,7 +329,7 @@ struct cpswx_intf { | |||
318 | u32 multi_if; | 329 | u32 multi_if; |
319 | struct list_head cpsw_intf_list; | 330 | struct list_head cpsw_intf_list; |
320 | struct timer_list timer; | 331 | struct timer_list timer; |
321 | u32 sgmii_link; | 332 | u32 link_state; |
322 | }; | 333 | }; |
323 | 334 | ||
324 | /* | 335 | /* |
@@ -1524,9 +1535,7 @@ static void _cpsw_adjust_link(struct cpswx_slave *slave, bool *link) | |||
1524 | 1535 | ||
1525 | if (phy->link) { | 1536 | if (phy->link) { |
1526 | mac_control = slave->mac_control; | 1537 | mac_control = slave->mac_control; |
1527 | mac_control |= MACSL_SIG_ENABLE(slave) | | 1538 | mac_control |= MACSL_DEFAULT_CONFIG(slave); |
1528 | MACSL_RX_ENABLE_EXT_CTL | | ||
1529 | MACSL_RX_ENABLE_CSF; | ||
1530 | /* enable forwarding */ | 1539 | /* enable forwarding */ |
1531 | cpsw_ale_control_set(slave->ale, slave_port, | 1540 | cpsw_ale_control_set(slave->ale, slave_port, |
1532 | ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); | 1541 | ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); |
@@ -1561,9 +1570,9 @@ static void cpsw_adjust_link(struct net_device *n_dev, void *context) | |||
1561 | _cpsw_adjust_link(slave, &link); | 1570 | _cpsw_adjust_link(slave, &link); |
1562 | 1571 | ||
1563 | if (link) | 1572 | if (link) |
1564 | netcp->link_state |= BIT(slave->slave_num); | 1573 | netcp->phy_link_state_mask |= BIT(slave->slave_num); |
1565 | else | 1574 | else |
1566 | netcp->link_state &= ~BIT(slave->slave_num); | 1575 | netcp->phy_link_state_mask &= ~BIT(slave->slave_num); |
1567 | } | 1576 | } |
1568 | 1577 | ||
1569 | /* | 1578 | /* |
@@ -1595,17 +1604,15 @@ static int cpsw_port_reset(struct cpswx_slave *slave) | |||
1595 | */ | 1604 | */ |
1596 | static void cpsw_port_config(struct cpswx_slave *slave, int max_rx_len) | 1605 | static void cpsw_port_config(struct cpswx_slave *slave, int max_rx_len) |
1597 | { | 1606 | { |
1598 | u32 mac_control; | ||
1599 | |||
1600 | if (max_rx_len > MAX_SIZE_STREAM_BUFFER) | 1607 | if (max_rx_len > MAX_SIZE_STREAM_BUFFER) |
1601 | max_rx_len = MAX_SIZE_STREAM_BUFFER; | 1608 | max_rx_len = MAX_SIZE_STREAM_BUFFER; |
1602 | 1609 | ||
1610 | slave->mac_control = MACSL_DEFAULT_CONFIG(slave); | ||
1611 | |||
1603 | __raw_writel(max_rx_len, &slave->sliver->rx_maxlen); | 1612 | __raw_writel(max_rx_len, &slave->sliver->rx_maxlen); |
1604 | 1613 | ||
1605 | mac_control = (MACSL_SIG_ENABLE(slave) | | 1614 | __iowmb(); |
1606 | MACSL_RX_ENABLE_EXT_CTL | | 1615 | __raw_writel(slave->mac_control, &slave->sliver->mac_control); |
1607 | MACSL_RX_ENABLE_CSF); | ||
1608 | __raw_writel(mac_control, &slave->sliver->mac_control); | ||
1609 | } | 1616 | } |
1610 | 1617 | ||
1611 | static void cpsw_slave_stop(struct cpswx_slave *slave, struct cpswx_priv *priv) | 1618 | static void cpsw_slave_stop(struct cpswx_slave *slave, struct cpswx_priv *priv) |
@@ -1624,15 +1631,17 @@ static void cpsw_slave_link(struct cpswx_slave *slave, | |||
1624 | struct cpswx_intf *cpsw_intf) | 1631 | struct cpswx_intf *cpsw_intf) |
1625 | { | 1632 | { |
1626 | struct netcp_priv *netcp = netdev_priv(cpsw_intf->ndev); | 1633 | struct netcp_priv *netcp = netdev_priv(cpsw_intf->ndev); |
1634 | int sn = slave->slave_num; | ||
1627 | 1635 | ||
1628 | if ((slave->link_interface == SGMII_LINK_MAC_PHY) || | 1636 | if ((slave->link_interface == SGMII_LINK_MAC_PHY) || |
1629 | (slave->link_interface == XGMII_LINK_MAC_PHY)) { | 1637 | (slave->link_interface == XGMII_LINK_MAC_PHY)) { |
1630 | if (netcp->link_state) | 1638 | /* check only the bit in phy_link_state_mask |
1631 | cpsw_intf->sgmii_link |= BIT(slave->slave_num); | 1639 | * that corresponds to the slave |
1632 | else | 1640 | */ |
1633 | cpsw_intf->sgmii_link &= ~BIT(slave->slave_num); | 1641 | if (!(netcp->phy_link_state_mask & BIT(sn))) |
1642 | cpsw_intf->link_state &= ~BIT(sn); | ||
1634 | } else if (slave->link_interface == XGMII_LINK_MAC_MAC_FORCED) | 1643 | } else if (slave->link_interface == XGMII_LINK_MAC_MAC_FORCED) |
1635 | cpsw_intf->sgmii_link |= BIT(slave->slave_num); | 1644 | cpsw_intf->link_state |= BIT(slave->slave_num); |
1636 | } | 1645 | } |
1637 | 1646 | ||
1638 | static void cpsw_slave_open(struct cpswx_slave *slave, | 1647 | static void cpsw_slave_open(struct cpswx_slave *slave, |
@@ -1661,9 +1670,6 @@ static void cpsw_slave_open(struct cpswx_slave *slave, | |||
1661 | 1670 | ||
1662 | cpsw_set_slave_mac(slave, cpsw_intf); | 1671 | cpsw_set_slave_mac(slave, cpsw_intf); |
1663 | 1672 | ||
1664 | slave->mac_control = MACSL_SIG_ENABLE(slave) | MACSL_RX_ENABLE_EXT_CTL | | ||
1665 | MACSL_RX_ENABLE_CSF; | ||
1666 | |||
1667 | slave_port = cpsw_get_slave_port(priv, slave->slave_num); | 1673 | slave_port = cpsw_get_slave_port(priv, slave->slave_num); |
1668 | 1674 | ||
1669 | slave->port_num = slave_port; | 1675 | slave->port_num = slave_port; |
@@ -1814,6 +1820,9 @@ static int cpswx_add_addr(void *intf_priv, struct netcp_addr *naddr) | |||
1814 | struct cpswx_intf *cpsw_intf = intf_priv; | 1820 | struct cpswx_intf *cpsw_intf = intf_priv; |
1815 | struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; | 1821 | struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; |
1816 | 1822 | ||
1823 | if (!cpsw_dev->opened) | ||
1824 | return -ENXIO; | ||
1825 | |||
1817 | dev_dbg(cpsw_dev->dev, "xgess adding address %pM, type %d\n", | 1826 | dev_dbg(cpsw_dev->dev, "xgess adding address %pM, type %d\n", |
1818 | naddr->addr, naddr->type); | 1827 | naddr->addr, naddr->type); |
1819 | 1828 | ||
@@ -1840,6 +1849,9 @@ static int cpswx_del_addr(void *intf_priv, struct netcp_addr *naddr) | |||
1840 | struct cpswx_intf *cpsw_intf = intf_priv; | 1849 | struct cpswx_intf *cpsw_intf = intf_priv; |
1841 | struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; | 1850 | struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; |
1842 | 1851 | ||
1852 | if (!cpsw_dev->opened) | ||
1853 | return -ENXIO; | ||
1854 | |||
1843 | dev_dbg(cpsw_dev->dev, "xgess deleting address %pM, type %d\n", | 1855 | dev_dbg(cpsw_dev->dev, "xgess deleting address %pM, type %d\n", |
1844 | naddr->addr, naddr->type); | 1856 | naddr->addr, naddr->type); |
1845 | 1857 | ||
@@ -1884,34 +1896,44 @@ static void cpswx_timer(unsigned long arg) | |||
1884 | struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; | 1896 | struct cpswx_priv *cpsw_dev = cpsw_intf->cpsw_priv; |
1885 | 1897 | ||
1886 | /* | 1898 | /* |
1887 | * if the slave's link_interface is not XGMII, sgmii_link bit | 1899 | * if the slave's link_interface is not XGMII, link_state bit |
1888 | * will not be set | 1900 | * will not be set |
1889 | */ | 1901 | */ |
1890 | if (cpsw_dev->multi_if) | 1902 | if (cpsw_dev->multi_if) |
1891 | cpsw_intf->sgmii_link = | 1903 | cpsw_intf->link_state = |
1892 | keystone_sgmii_get_port_link(cpsw_dev->sgmii_port_regs, | 1904 | keystone_sgmii_get_port_link(cpsw_dev->sgmii_port_regs, |
1893 | cpsw_intf->slave_port); | 1905 | cpsw_intf->slave_port); |
1894 | else | 1906 | else |
1895 | cpsw_intf->sgmii_link = | 1907 | cpsw_intf->link_state = |
1896 | keystone_sgmii_link_status(cpsw_dev->sgmii_port_regs, | 1908 | keystone_sgmii_link_status(cpsw_dev->sgmii_port_regs, |
1897 | cpsw_intf->num_slaves); | 1909 | cpsw_intf->num_slaves); |
1898 | 1910 | ||
1911 | /* if MAC-to-PHY, check phy link status also | ||
1912 | * to conclude the intf link's status | ||
1913 | */ | ||
1899 | for_each_slave(cpsw_intf, cpsw_slave_link, cpsw_intf); | 1914 | for_each_slave(cpsw_intf, cpsw_slave_link, cpsw_intf); |
1900 | 1915 | ||
1901 | /* FIXME: Don't aggregate link statuses in multi-interface case */ | 1916 | /* Is this the right logic? |
1902 | if (cpsw_intf->sgmii_link) { | 1917 | * multi_if & MAC_PHY: phy state machine already reported carrier |
1903 | /* link ON */ | 1918 | * multi_if & !MAC_PHY: report carrier |
1904 | if (!netif_carrier_ok(cpsw_intf->ndev)) | 1919 | * !multi_if: any one slave up means intf is up, reporting carrier |
1920 | * here corrects what phy state machine (if it exists) | ||
1921 | * might have reported. | ||
1922 | */ | ||
1923 | if (!cpsw_dev->multi_if || | ||
1924 | (cpsw_dev->multi_if && | ||
1925 | (cpsw_intf->slaves->link_interface != SGMII_LINK_MAC_PHY) && | ||
1926 | (cpsw_intf->slaves->link_interface != XGMII_LINK_MAC_PHY))) { | ||
1927 | if (cpsw_intf->link_state) | ||
1905 | netif_carrier_on(cpsw_intf->ndev); | 1928 | netif_carrier_on(cpsw_intf->ndev); |
1906 | } else { | 1929 | else |
1907 | /* link OFF */ | ||
1908 | if (netif_carrier_ok(cpsw_intf->ndev)) | ||
1909 | netif_carrier_off(cpsw_intf->ndev); | 1930 | netif_carrier_off(cpsw_intf->ndev); |
1910 | } | 1931 | } |
1911 | 1932 | ||
1912 | spin_lock_bh(&cpsw_dev->hw_stats_lock); | 1933 | /* A timer runs as a BH, no need to block them */ |
1934 | spin_lock(&cpsw_dev->hw_stats_lock); | ||
1913 | cpswx_update_stats(cpsw_dev, NULL); | 1935 | cpswx_update_stats(cpsw_dev, NULL); |
1914 | spin_unlock_bh(&cpsw_dev->hw_stats_lock); | 1936 | spin_unlock(&cpsw_dev->hw_stats_lock); |
1915 | 1937 | ||
1916 | cpsw_intf->timer.expires = jiffies + (HZ/10); | 1938 | cpsw_intf->timer.expires = jiffies + (HZ/10); |
1917 | add_timer(&cpsw_intf->timer); | 1939 | add_timer(&cpsw_intf->timer); |
@@ -2017,6 +2039,7 @@ static int cpswx_open(void *intf_mod_priv, struct net_device *ndev) | |||
2017 | PSTREAM_ROUTE_DMA); | 2039 | PSTREAM_ROUTE_DMA); |
2018 | #endif | 2040 | #endif |
2019 | 2041 | ||
2042 | cpsw_dev->opened = 1; | ||
2020 | return 0; | 2043 | return 0; |
2021 | 2044 | ||
2022 | ale_fail: | 2045 | ale_fail: |
@@ -2051,6 +2074,7 @@ static int cpswx_close(void *intf_modpriv, struct net_device *ndev) | |||
2051 | clk_disable_unprepare(cpsw_dev->clk); | 2074 | clk_disable_unprepare(cpsw_dev->clk); |
2052 | clk_put(cpsw_dev->clk); | 2075 | clk_put(cpsw_dev->clk); |
2053 | 2076 | ||
2077 | cpsw_dev->opened = 0; | ||
2054 | return 0; | 2078 | return 0; |
2055 | } | 2079 | } |
2056 | 2080 | ||