aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-04-11 17:48:01 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-19 15:01:17 -0400
commitb628ed986d681c708aec64418c2c7f6a6b715855 (patch)
tree6ade1dbf518f3b1605046b8f3ee36bf988c393a6 /drivers
parent4f44d8ba09280a7f0887ab60277940d6c72f2b43 (diff)
sky2: EC-U performance and jumbo support
The Yukon EC Ultra chips have transmit settings for store and forward and PCI buffering. By setting these appropriately, normal performance goes from 750Mbytes/sec to 940Mbytes/sec (non-jumbo). It is also possible to do Jumbo mode, but it means turning off TSO and checksum offload so the performance gets worse. There isn't enough buffering for checksum offload to work. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sky2.c85
-rw-r--r--drivers/net/sky2.h8
2 files changed, 68 insertions, 25 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 910c600a6caf..4d1ec78c437a 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -743,12 +743,17 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
743 if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { 743 if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
744 sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); 744 sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
745 sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); 745 sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
746 if (hw->dev[port]->mtu > ETH_DATA_LEN) { 746
747 /* set Tx GMAC FIFO Almost Empty Threshold */ 747 /* set Tx GMAC FIFO Almost Empty Threshold */
748 sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), 0x180); 748 sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
749 /* Disable Store & Forward mode for TX */ 749 (ECU_JUMBO_WM << 16) | ECU_AE_THR);
750 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); 750
751 } 751 if (hw->dev[port]->mtu > ETH_DATA_LEN)
752 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
753 TX_JUMBO_ENA | TX_STFW_DIS);
754 else
755 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
756 TX_JUMBO_DIS | TX_STFW_ENA);
752 } 757 }
753 758
754} 759}
@@ -1281,7 +1286,7 @@ static int sky2_up(struct net_device *dev)
1281 /* Set almost empty threshold */ 1286 /* Set almost empty threshold */
1282 if (hw->chip_id == CHIP_ID_YUKON_EC_U 1287 if (hw->chip_id == CHIP_ID_YUKON_EC_U
1283 && hw->chip_rev == CHIP_REV_YU_EC_U_A0) 1288 && hw->chip_rev == CHIP_REV_YU_EC_U_A0)
1284 sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0); 1289 sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV);
1285 1290
1286 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, 1291 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
1287 TX_RING_SIZE - 1); 1292 TX_RING_SIZE - 1);
@@ -1587,13 +1592,6 @@ static int sky2_down(struct net_device *dev)
1587 sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), 1592 sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
1588 RB_RST_SET | RB_DIS_OP_MD); 1593 RB_RST_SET | RB_DIS_OP_MD);
1589 1594
1590 /* WA for dev. #4.209 */
1591 if (hw->chip_id == CHIP_ID_YUKON_EC_U
1592 && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0))
1593 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1594 sky2->speed != SPEED_1000 ?
1595 TX_STFW_ENA : TX_STFW_DIS);
1596
1597 ctrl = gma_read16(hw, port, GM_GP_CTRL); 1595 ctrl = gma_read16(hw, port, GM_GP_CTRL);
1598 ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); 1596 ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
1599 gma_write16(hw, port, GM_GP_CTRL, ctrl); 1597 gma_write16(hw, port, GM_GP_CTRL, ctrl);
@@ -1893,6 +1891,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1893{ 1891{
1894 struct sky2_port *sky2 = netdev_priv(dev); 1892 struct sky2_port *sky2 = netdev_priv(dev);
1895 struct sky2_hw *hw = sky2->hw; 1893 struct sky2_hw *hw = sky2->hw;
1894 unsigned port = sky2->port;
1896 int err; 1895 int err;
1897 u16 ctl, mode; 1896 u16 ctl, mode;
1898 u32 imask; 1897 u32 imask;
@@ -1900,10 +1899,6 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1900 if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) 1899 if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
1901 return -EINVAL; 1900 return -EINVAL;
1902 1901
1903 /* TSO on Yukon Ultra and MTU > 1500 not supported */
1904 if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN)
1905 dev->features &= ~NETIF_F_TSO;
1906
1907 if (!netif_running(dev)) { 1902 if (!netif_running(dev)) {
1908 dev->mtu = new_mtu; 1903 dev->mtu = new_mtu;
1909 return 0; 1904 return 0;
@@ -1918,8 +1913,18 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1918 1913
1919 synchronize_irq(hw->pdev->irq); 1914 synchronize_irq(hw->pdev->irq);
1920 1915
1921 ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); 1916 if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
1922 gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); 1917 if (new_mtu > ETH_DATA_LEN) {
1918 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1919 TX_JUMBO_ENA | TX_STFW_DIS);
1920 dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
1921 } else
1922 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1923 TX_JUMBO_DIS | TX_STFW_ENA);
1924 }
1925
1926 ctl = gma_read16(hw, port, GM_GP_CTRL);
1927 gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
1923 sky2_rx_stop(sky2); 1928 sky2_rx_stop(sky2);
1924 sky2_rx_clean(sky2); 1929 sky2_rx_clean(sky2);
1925 1930
@@ -1931,9 +1936,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1931 if (dev->mtu > ETH_DATA_LEN) 1936 if (dev->mtu > ETH_DATA_LEN)
1932 mode |= GM_SMOD_JUMBO_ENA; 1937 mode |= GM_SMOD_JUMBO_ENA;
1933 1938
1934 gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode); 1939 gma_write16(hw, port, GM_SERIAL_MODE, mode);
1935 1940
1936 sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); 1941 sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);
1937 1942
1938 err = sky2_rx_start(sky2); 1943 err = sky2_rx_start(sky2);
1939 sky2_write32(hw, B0_IMSK, imask); 1944 sky2_write32(hw, B0_IMSK, imask);
@@ -1941,7 +1946,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1941 if (err) 1946 if (err)
1942 dev_close(dev); 1947 dev_close(dev);
1943 else { 1948 else {
1944 gma_write16(hw, sky2->port, GM_GP_CTRL, ctl); 1949 gma_write16(hw, port, GM_GP_CTRL, ctl);
1945 1950
1946 netif_poll_enable(hw->dev[0]); 1951 netif_poll_enable(hw->dev[0]);
1947 netif_wake_queue(dev); 1952 netif_wake_queue(dev);
@@ -3334,6 +3339,36 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
3334 regs->len - B3_RI_WTO_R1); 3339 regs->len - B3_RI_WTO_R1);
3335} 3340}
3336 3341
3342/* In order to do Jumbo packets on these chips, need to turn off the
3343 * transmit store/forward. Therefore checksum offload won't work.
3344 */
3345static int no_tx_offload(struct net_device *dev)
3346{
3347 const struct sky2_port *sky2 = netdev_priv(dev);
3348 const struct sky2_hw *hw = sky2->hw;
3349
3350 return dev->mtu > ETH_DATA_LEN &&
3351 (hw->chip_id == CHIP_ID_YUKON_EX
3352 || hw->chip_id == CHIP_ID_YUKON_EC_U);
3353}
3354
3355static int sky2_set_tx_csum(struct net_device *dev, u32 data)
3356{
3357 if (data && no_tx_offload(dev))
3358 return -EINVAL;
3359
3360 return ethtool_op_set_tx_csum(dev, data);
3361}
3362
3363
3364static int sky2_set_tso(struct net_device *dev, u32 data)
3365{
3366 if (data && no_tx_offload(dev))
3367 return -EINVAL;
3368
3369 return ethtool_op_set_tso(dev, data);
3370}
3371
3337static const struct ethtool_ops sky2_ethtool_ops = { 3372static const struct ethtool_ops sky2_ethtool_ops = {
3338 .get_settings = sky2_get_settings, 3373 .get_settings = sky2_get_settings,
3339 .set_settings = sky2_set_settings, 3374 .set_settings = sky2_set_settings,
@@ -3349,9 +3384,9 @@ static const struct ethtool_ops sky2_ethtool_ops = {
3349 .get_sg = ethtool_op_get_sg, 3384 .get_sg = ethtool_op_get_sg,
3350 .set_sg = ethtool_op_set_sg, 3385 .set_sg = ethtool_op_set_sg,
3351 .get_tx_csum = ethtool_op_get_tx_csum, 3386 .get_tx_csum = ethtool_op_get_tx_csum,
3352 .set_tx_csum = ethtool_op_set_tx_csum, 3387 .set_tx_csum = sky2_set_tx_csum,
3353 .get_tso = ethtool_op_get_tso, 3388 .get_tso = ethtool_op_get_tso,
3354 .set_tso = ethtool_op_set_tso, 3389 .set_tso = sky2_set_tso,
3355 .get_rx_csum = sky2_get_rx_csum, 3390 .get_rx_csum = sky2_get_rx_csum,
3356 .set_rx_csum = sky2_set_rx_csum, 3391 .set_rx_csum = sky2_set_rx_csum,
3357 .get_strings = sky2_get_strings, 3392 .get_strings = sky2_get_strings,
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 9ca4a2c061c6..5efb5afc45ba 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -741,6 +741,11 @@ enum {
741 TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */ 741 TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */
742 TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */ 742 TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */
743 TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */ 743 TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */
744
745 /* Threshold values for Yukon-EC Ultra and Extreme */
746 ECU_AE_THR = 0x0070, /* Almost Empty Threshold */
747 ECU_TXFF_LEV = 0x01a0, /* Tx BMU FIFO Level */
748 ECU_JUMBO_WM = 0x0080, /* Jumbo Mode Watermark */
744}; 749};
745 750
746/* Descriptor Poll Timer Registers */ 751/* Descriptor Poll Timer Registers */
@@ -1634,6 +1639,9 @@ enum {
1634 TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */ 1639 TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */
1635 TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */ 1640 TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */
1636 1641
1642 TX_JUMBO_ENA = 1<<23,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */
1643 TX_JUMBO_DIS = 1<<22,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */
1644
1637 GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */ 1645 GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */
1638 GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */ 1646 GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */
1639 GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */ 1647 GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */