diff options
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 223 |
1 files changed, 135 insertions, 88 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a4a58e4e93a1..b2949035f66a 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -11,8 +11,7 @@ | |||
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
14 | * the Free Software Foundation; either version 2 of the License, or | 14 | * the Free Software Foundation; either version 2 of the License. |
15 | * (at your option) any later version. | ||
16 | * | 15 | * |
17 | * This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
@@ -43,7 +42,7 @@ | |||
43 | #include "skge.h" | 42 | #include "skge.h" |
44 | 43 | ||
45 | #define DRV_NAME "skge" | 44 | #define DRV_NAME "skge" |
46 | #define DRV_VERSION "1.8" | 45 | #define DRV_VERSION "1.9" |
47 | #define PFX DRV_NAME " " | 46 | #define PFX DRV_NAME " " |
48 | 47 | ||
49 | #define DEFAULT_TX_RING_SIZE 128 | 48 | #define DEFAULT_TX_RING_SIZE 128 |
@@ -197,8 +196,8 @@ static u32 skge_supported_modes(const struct skge_hw *hw) | |||
197 | else if (hw->chip_id == CHIP_ID_YUKON) | 196 | else if (hw->chip_id == CHIP_ID_YUKON) |
198 | supported &= ~SUPPORTED_1000baseT_Half; | 197 | supported &= ~SUPPORTED_1000baseT_Half; |
199 | } else | 198 | } else |
200 | supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE | 199 | supported = SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half |
201 | | SUPPORTED_Autoneg; | 200 | | SUPPORTED_FIBRE | SUPPORTED_Autoneg; |
202 | 201 | ||
203 | return supported; | 202 | return supported; |
204 | } | 203 | } |
@@ -487,31 +486,37 @@ static void skge_get_pauseparam(struct net_device *dev, | |||
487 | { | 486 | { |
488 | struct skge_port *skge = netdev_priv(dev); | 487 | struct skge_port *skge = netdev_priv(dev); |
489 | 488 | ||
490 | ecmd->tx_pause = (skge->flow_control == FLOW_MODE_LOC_SEND) | 489 | ecmd->rx_pause = (skge->flow_control == FLOW_MODE_SYMMETRIC) |
491 | || (skge->flow_control == FLOW_MODE_SYMMETRIC); | 490 | || (skge->flow_control == FLOW_MODE_SYM_OR_REM); |
492 | ecmd->rx_pause = (skge->flow_control == FLOW_MODE_REM_SEND) | 491 | ecmd->tx_pause = ecmd->rx_pause || (skge->flow_control == FLOW_MODE_LOC_SEND); |
493 | || (skge->flow_control == FLOW_MODE_SYMMETRIC); | ||
494 | 492 | ||
495 | ecmd->autoneg = skge->autoneg; | 493 | ecmd->autoneg = ecmd->rx_pause || ecmd->tx_pause; |
496 | } | 494 | } |
497 | 495 | ||
498 | static int skge_set_pauseparam(struct net_device *dev, | 496 | static int skge_set_pauseparam(struct net_device *dev, |
499 | struct ethtool_pauseparam *ecmd) | 497 | struct ethtool_pauseparam *ecmd) |
500 | { | 498 | { |
501 | struct skge_port *skge = netdev_priv(dev); | 499 | struct skge_port *skge = netdev_priv(dev); |
500 | struct ethtool_pauseparam old; | ||
502 | 501 | ||
503 | skge->autoneg = ecmd->autoneg; | 502 | skge_get_pauseparam(dev, &old); |
504 | if (ecmd->rx_pause && ecmd->tx_pause) | 503 | |
505 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 504 | if (ecmd->autoneg != old.autoneg) |
506 | else if (ecmd->rx_pause && !ecmd->tx_pause) | 505 | skge->flow_control = ecmd->autoneg ? FLOW_MODE_NONE : FLOW_MODE_SYMMETRIC; |
507 | skge->flow_control = FLOW_MODE_REM_SEND; | 506 | else { |
508 | else if (!ecmd->rx_pause && ecmd->tx_pause) | 507 | if (ecmd->rx_pause && ecmd->tx_pause) |
509 | skge->flow_control = FLOW_MODE_LOC_SEND; | 508 | skge->flow_control = FLOW_MODE_SYMMETRIC; |
510 | else | 509 | else if (ecmd->rx_pause && !ecmd->tx_pause) |
511 | skge->flow_control = FLOW_MODE_NONE; | 510 | skge->flow_control = FLOW_MODE_SYM_OR_REM; |
511 | else if (!ecmd->rx_pause && ecmd->tx_pause) | ||
512 | skge->flow_control = FLOW_MODE_LOC_SEND; | ||
513 | else | ||
514 | skge->flow_control = FLOW_MODE_NONE; | ||
515 | } | ||
512 | 516 | ||
513 | if (netif_running(dev)) | 517 | if (netif_running(dev)) |
514 | skge_phy_reset(skge); | 518 | skge_phy_reset(skge); |
519 | |||
515 | return 0; | 520 | return 0; |
516 | } | 521 | } |
517 | 522 | ||
@@ -854,6 +859,23 @@ static int skge_rx_fill(struct net_device *dev) | |||
854 | return 0; | 859 | return 0; |
855 | } | 860 | } |
856 | 861 | ||
862 | static const char *skge_pause(enum pause_status status) | ||
863 | { | ||
864 | switch(status) { | ||
865 | case FLOW_STAT_NONE: | ||
866 | return "none"; | ||
867 | case FLOW_STAT_REM_SEND: | ||
868 | return "rx only"; | ||
869 | case FLOW_STAT_LOC_SEND: | ||
870 | return "tx_only"; | ||
871 | case FLOW_STAT_SYMMETRIC: /* Both station may send PAUSE */ | ||
872 | return "both"; | ||
873 | default: | ||
874 | return "indeterminated"; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | |||
857 | static void skge_link_up(struct skge_port *skge) | 879 | static void skge_link_up(struct skge_port *skge) |
858 | { | 880 | { |
859 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), | 881 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), |
@@ -862,16 +884,13 @@ static void skge_link_up(struct skge_port *skge) | |||
862 | netif_carrier_on(skge->netdev); | 884 | netif_carrier_on(skge->netdev); |
863 | netif_wake_queue(skge->netdev); | 885 | netif_wake_queue(skge->netdev); |
864 | 886 | ||
865 | if (netif_msg_link(skge)) | 887 | if (netif_msg_link(skge)) { |
866 | printk(KERN_INFO PFX | 888 | printk(KERN_INFO PFX |
867 | "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", | 889 | "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", |
868 | skge->netdev->name, skge->speed, | 890 | skge->netdev->name, skge->speed, |
869 | skge->duplex == DUPLEX_FULL ? "full" : "half", | 891 | skge->duplex == DUPLEX_FULL ? "full" : "half", |
870 | (skge->flow_control == FLOW_MODE_NONE) ? "none" : | 892 | skge_pause(skge->flow_status)); |
871 | (skge->flow_control == FLOW_MODE_LOC_SEND) ? "tx only" : | 893 | } |
872 | (skge->flow_control == FLOW_MODE_REM_SEND) ? "rx only" : | ||
873 | (skge->flow_control == FLOW_MODE_SYMMETRIC) ? "tx and rx" : | ||
874 | "unknown"); | ||
875 | } | 894 | } |
876 | 895 | ||
877 | static void skge_link_down(struct skge_port *skge) | 896 | static void skge_link_down(struct skge_port *skge) |
@@ -884,6 +903,29 @@ static void skge_link_down(struct skge_port *skge) | |||
884 | printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); | 903 | printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); |
885 | } | 904 | } |
886 | 905 | ||
906 | |||
907 | static void xm_link_down(struct skge_hw *hw, int port) | ||
908 | { | ||
909 | struct net_device *dev = hw->dev[port]; | ||
910 | struct skge_port *skge = netdev_priv(dev); | ||
911 | u16 cmd, msk; | ||
912 | |||
913 | if (hw->phy_type == SK_PHY_XMAC) { | ||
914 | msk = xm_read16(hw, port, XM_IMSK); | ||
915 | msk |= XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND; | ||
916 | xm_write16(hw, port, XM_IMSK, msk); | ||
917 | } | ||
918 | |||
919 | cmd = xm_read16(hw, port, XM_MMU_CMD); | ||
920 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | ||
921 | xm_write16(hw, port, XM_MMU_CMD, cmd); | ||
922 | /* dummy read to ensure writing */ | ||
923 | (void) xm_read16(hw, port, XM_MMU_CMD); | ||
924 | |||
925 | if (netif_carrier_ok(dev)) | ||
926 | skge_link_down(skge); | ||
927 | } | ||
928 | |||
887 | static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) | 929 | static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) |
888 | { | 930 | { |
889 | int i; | 931 | int i; |
@@ -992,7 +1034,15 @@ static const u16 phy_pause_map[] = { | |||
992 | [FLOW_MODE_NONE] = 0, | 1034 | [FLOW_MODE_NONE] = 0, |
993 | [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, | 1035 | [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, |
994 | [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, | 1036 | [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, |
995 | [FLOW_MODE_REM_SEND] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, | 1037 | [FLOW_MODE_SYM_OR_REM] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, |
1038 | }; | ||
1039 | |||
1040 | /* special defines for FIBER (88E1011S only) */ | ||
1041 | static const u16 fiber_pause_map[] = { | ||
1042 | [FLOW_MODE_NONE] = PHY_X_P_NO_PAUSE, | ||
1043 | [FLOW_MODE_LOC_SEND] = PHY_X_P_ASYM_MD, | ||
1044 | [FLOW_MODE_SYMMETRIC] = PHY_X_P_SYM_MD, | ||
1045 | [FLOW_MODE_SYM_OR_REM] = PHY_X_P_BOTH_MD, | ||
996 | }; | 1046 | }; |
997 | 1047 | ||
998 | 1048 | ||
@@ -1008,14 +1058,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) | |||
1008 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); | 1058 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); |
1009 | 1059 | ||
1010 | if ((status & PHY_ST_LSYNC) == 0) { | 1060 | if ((status & PHY_ST_LSYNC) == 0) { |
1011 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); | 1061 | xm_link_down(hw, port); |
1012 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | ||
1013 | xm_write16(hw, port, XM_MMU_CMD, cmd); | ||
1014 | /* dummy read to ensure writing */ | ||
1015 | (void) xm_read16(hw, port, XM_MMU_CMD); | ||
1016 | |||
1017 | if (netif_carrier_ok(dev)) | ||
1018 | skge_link_down(skge); | ||
1019 | return; | 1062 | return; |
1020 | } | 1063 | } |
1021 | 1064 | ||
@@ -1048,20 +1091,19 @@ static void bcom_check_link(struct skge_hw *hw, int port) | |||
1048 | return; | 1091 | return; |
1049 | } | 1092 | } |
1050 | 1093 | ||
1051 | |||
1052 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ | 1094 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ |
1053 | switch (aux & PHY_B_AS_PAUSE_MSK) { | 1095 | switch (aux & PHY_B_AS_PAUSE_MSK) { |
1054 | case PHY_B_AS_PAUSE_MSK: | 1096 | case PHY_B_AS_PAUSE_MSK: |
1055 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 1097 | skge->flow_status = FLOW_STAT_SYMMETRIC; |
1056 | break; | 1098 | break; |
1057 | case PHY_B_AS_PRR: | 1099 | case PHY_B_AS_PRR: |
1058 | skge->flow_control = FLOW_MODE_REM_SEND; | 1100 | skge->flow_status = FLOW_STAT_REM_SEND; |
1059 | break; | 1101 | break; |
1060 | case PHY_B_AS_PRT: | 1102 | case PHY_B_AS_PRT: |
1061 | skge->flow_control = FLOW_MODE_LOC_SEND; | 1103 | skge->flow_status = FLOW_STAT_LOC_SEND; |
1062 | break; | 1104 | break; |
1063 | default: | 1105 | default: |
1064 | skge->flow_control = FLOW_MODE_NONE; | 1106 | skge->flow_status = FLOW_STAT_NONE; |
1065 | } | 1107 | } |
1066 | skge->speed = SPEED_1000; | 1108 | skge->speed = SPEED_1000; |
1067 | } | 1109 | } |
@@ -1191,17 +1233,7 @@ static void xm_phy_init(struct skge_port *skge) | |||
1191 | if (skge->advertising & ADVERTISED_1000baseT_Full) | 1233 | if (skge->advertising & ADVERTISED_1000baseT_Full) |
1192 | ctrl |= PHY_X_AN_FD; | 1234 | ctrl |= PHY_X_AN_FD; |
1193 | 1235 | ||
1194 | switch(skge->flow_control) { | 1236 | ctrl |= fiber_pause_map[skge->flow_control]; |
1195 | case FLOW_MODE_NONE: | ||
1196 | ctrl |= PHY_X_P_NO_PAUSE; | ||
1197 | break; | ||
1198 | case FLOW_MODE_LOC_SEND: | ||
1199 | ctrl |= PHY_X_P_ASYM_MD; | ||
1200 | break; | ||
1201 | case FLOW_MODE_SYMMETRIC: | ||
1202 | ctrl |= PHY_X_P_BOTH_MD; | ||
1203 | break; | ||
1204 | } | ||
1205 | 1237 | ||
1206 | xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl); | 1238 | xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl); |
1207 | 1239 | ||
@@ -1235,14 +1267,7 @@ static void xm_check_link(struct net_device *dev) | |||
1235 | status = xm_phy_read(hw, port, PHY_XMAC_STAT); | 1267 | status = xm_phy_read(hw, port, PHY_XMAC_STAT); |
1236 | 1268 | ||
1237 | if ((status & PHY_ST_LSYNC) == 0) { | 1269 | if ((status & PHY_ST_LSYNC) == 0) { |
1238 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); | 1270 | xm_link_down(hw, port); |
1239 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | ||
1240 | xm_write16(hw, port, XM_MMU_CMD, cmd); | ||
1241 | /* dummy read to ensure writing */ | ||
1242 | (void) xm_read16(hw, port, XM_MMU_CMD); | ||
1243 | |||
1244 | if (netif_carrier_ok(dev)) | ||
1245 | skge_link_down(skge); | ||
1246 | return; | 1271 | return; |
1247 | } | 1272 | } |
1248 | 1273 | ||
@@ -1276,15 +1301,20 @@ static void xm_check_link(struct net_device *dev) | |||
1276 | } | 1301 | } |
1277 | 1302 | ||
1278 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ | 1303 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ |
1279 | if (lpa & PHY_X_P_SYM_MD) | 1304 | if ((skge->flow_control == FLOW_MODE_SYMMETRIC || |
1280 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 1305 | skge->flow_control == FLOW_MODE_SYM_OR_REM) && |
1281 | else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) | 1306 | (lpa & PHY_X_P_SYM_MD)) |
1282 | skge->flow_control = FLOW_MODE_REM_SEND; | 1307 | skge->flow_status = FLOW_STAT_SYMMETRIC; |
1283 | else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) | 1308 | else if (skge->flow_control == FLOW_MODE_SYM_OR_REM && |
1284 | skge->flow_control = FLOW_MODE_LOC_SEND; | 1309 | (lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) |
1310 | /* Enable PAUSE receive, disable PAUSE transmit */ | ||
1311 | skge->flow_status = FLOW_STAT_REM_SEND; | ||
1312 | else if (skge->flow_control == FLOW_MODE_LOC_SEND && | ||
1313 | (lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) | ||
1314 | /* Disable PAUSE receive, enable PAUSE transmit */ | ||
1315 | skge->flow_status = FLOW_STAT_LOC_SEND; | ||
1285 | else | 1316 | else |
1286 | skge->flow_control = FLOW_MODE_NONE; | 1317 | skge->flow_status = FLOW_STAT_NONE; |
1287 | |||
1288 | 1318 | ||
1289 | skge->speed = SPEED_1000; | 1319 | skge->speed = SPEED_1000; |
1290 | } | 1320 | } |
@@ -1568,6 +1598,10 @@ static void genesis_mac_intr(struct skge_hw *hw, int port) | |||
1568 | printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", | 1598 | printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", |
1569 | skge->netdev->name, status); | 1599 | skge->netdev->name, status); |
1570 | 1600 | ||
1601 | if (hw->phy_type == SK_PHY_XMAC && | ||
1602 | (status & (XM_IS_INP_ASS | XM_IS_LIPA_RC))) | ||
1603 | xm_link_down(hw, port); | ||
1604 | |||
1571 | if (status & XM_IS_TXF_UR) { | 1605 | if (status & XM_IS_TXF_UR) { |
1572 | xm_write32(hw, port, XM_MODE, XM_MD_FTF); | 1606 | xm_write32(hw, port, XM_MODE, XM_MD_FTF); |
1573 | ++skge->net_stats.tx_fifo_errors; | 1607 | ++skge->net_stats.tx_fifo_errors; |
@@ -1582,7 +1616,7 @@ static void genesis_link_up(struct skge_port *skge) | |||
1582 | { | 1616 | { |
1583 | struct skge_hw *hw = skge->hw; | 1617 | struct skge_hw *hw = skge->hw; |
1584 | int port = skge->port; | 1618 | int port = skge->port; |
1585 | u16 cmd; | 1619 | u16 cmd, msk; |
1586 | u32 mode; | 1620 | u32 mode; |
1587 | 1621 | ||
1588 | cmd = xm_read16(hw, port, XM_MMU_CMD); | 1622 | cmd = xm_read16(hw, port, XM_MMU_CMD); |
@@ -1591,8 +1625,8 @@ static void genesis_link_up(struct skge_port *skge) | |||
1591 | * enabling pause frame reception is required for 1000BT | 1625 | * enabling pause frame reception is required for 1000BT |
1592 | * because the XMAC is not reset if the link is going down | 1626 | * because the XMAC is not reset if the link is going down |
1593 | */ | 1627 | */ |
1594 | if (skge->flow_control == FLOW_MODE_NONE || | 1628 | if (skge->flow_status == FLOW_STAT_NONE || |
1595 | skge->flow_control == FLOW_MODE_LOC_SEND) | 1629 | skge->flow_status == FLOW_STAT_LOC_SEND) |
1596 | /* Disable Pause Frame Reception */ | 1630 | /* Disable Pause Frame Reception */ |
1597 | cmd |= XM_MMU_IGN_PF; | 1631 | cmd |= XM_MMU_IGN_PF; |
1598 | else | 1632 | else |
@@ -1602,8 +1636,8 @@ static void genesis_link_up(struct skge_port *skge) | |||
1602 | xm_write16(hw, port, XM_MMU_CMD, cmd); | 1636 | xm_write16(hw, port, XM_MMU_CMD, cmd); |
1603 | 1637 | ||
1604 | mode = xm_read32(hw, port, XM_MODE); | 1638 | mode = xm_read32(hw, port, XM_MODE); |
1605 | if (skge->flow_control == FLOW_MODE_SYMMETRIC || | 1639 | if (skge->flow_status== FLOW_STAT_SYMMETRIC || |
1606 | skge->flow_control == FLOW_MODE_LOC_SEND) { | 1640 | skge->flow_status == FLOW_STAT_LOC_SEND) { |
1607 | /* | 1641 | /* |
1608 | * Configure Pause Frame Generation | 1642 | * Configure Pause Frame Generation |
1609 | * Use internal and external Pause Frame Generation. | 1643 | * Use internal and external Pause Frame Generation. |
@@ -1631,7 +1665,11 @@ static void genesis_link_up(struct skge_port *skge) | |||
1631 | } | 1665 | } |
1632 | 1666 | ||
1633 | xm_write32(hw, port, XM_MODE, mode); | 1667 | xm_write32(hw, port, XM_MODE, mode); |
1634 | xm_write16(hw, port, XM_IMSK, XM_DEF_MSK); | 1668 | msk = XM_DEF_MSK; |
1669 | if (hw->phy_type != SK_PHY_XMAC) | ||
1670 | msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */ | ||
1671 | |||
1672 | xm_write16(hw, port, XM_IMSK, msk); | ||
1635 | xm_read16(hw, port, XM_ISRC); | 1673 | xm_read16(hw, port, XM_ISRC); |
1636 | 1674 | ||
1637 | /* get MMU Command Reg. */ | 1675 | /* get MMU Command Reg. */ |
@@ -1779,11 +1817,17 @@ static void yukon_init(struct skge_hw *hw, int port) | |||
1779 | adv |= PHY_M_AN_10_FD; | 1817 | adv |= PHY_M_AN_10_FD; |
1780 | if (skge->advertising & ADVERTISED_10baseT_Half) | 1818 | if (skge->advertising & ADVERTISED_10baseT_Half) |
1781 | adv |= PHY_M_AN_10_HD; | 1819 | adv |= PHY_M_AN_10_HD; |
1782 | } else /* special defines for FIBER (88E1011S only) */ | ||
1783 | adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; | ||
1784 | 1820 | ||
1785 | /* Set Flow-control capabilities */ | 1821 | /* Set Flow-control capabilities */ |
1786 | adv |= phy_pause_map[skge->flow_control]; | 1822 | adv |= phy_pause_map[skge->flow_control]; |
1823 | } else { | ||
1824 | if (skge->advertising & ADVERTISED_1000baseT_Full) | ||
1825 | adv |= PHY_M_AN_1000X_AFD; | ||
1826 | if (skge->advertising & ADVERTISED_1000baseT_Half) | ||
1827 | adv |= PHY_M_AN_1000X_AHD; | ||
1828 | |||
1829 | adv |= fiber_pause_map[skge->flow_control]; | ||
1830 | } | ||
1787 | 1831 | ||
1788 | /* Restart Auto-negotiation */ | 1832 | /* Restart Auto-negotiation */ |
1789 | ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; | 1833 | ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; |
@@ -1917,6 +1961,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1917 | case FLOW_MODE_LOC_SEND: | 1961 | case FLOW_MODE_LOC_SEND: |
1918 | /* disable Rx flow-control */ | 1962 | /* disable Rx flow-control */ |
1919 | reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; | 1963 | reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; |
1964 | break; | ||
1965 | case FLOW_MODE_SYMMETRIC: | ||
1966 | case FLOW_MODE_SYM_OR_REM: | ||
1967 | /* enable Tx & Rx flow-control */ | ||
1968 | break; | ||
1920 | } | 1969 | } |
1921 | 1970 | ||
1922 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1971 | gma_write16(hw, port, GM_GP_CTRL, reg); |
@@ -2111,13 +2160,11 @@ static void yukon_link_down(struct skge_port *skge) | |||
2111 | ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); | 2160 | ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); |
2112 | gma_write16(hw, port, GM_GP_CTRL, ctrl); | 2161 | gma_write16(hw, port, GM_GP_CTRL, ctrl); |
2113 | 2162 | ||
2114 | if (skge->flow_control == FLOW_MODE_REM_SEND) { | 2163 | if (skge->flow_status == FLOW_STAT_REM_SEND) { |
2164 | ctrl = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); | ||
2165 | ctrl |= PHY_M_AN_ASP; | ||
2115 | /* restore Asymmetric Pause bit */ | 2166 | /* restore Asymmetric Pause bit */ |
2116 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, | 2167 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl); |
2117 | gm_phy_read(hw, port, | ||
2118 | PHY_MARV_AUNE_ADV) | ||
2119 | | PHY_M_AN_ASP); | ||
2120 | |||
2121 | } | 2168 | } |
2122 | 2169 | ||
2123 | yukon_reset(hw, port); | 2170 | yukon_reset(hw, port); |
@@ -2164,19 +2211,19 @@ static void yukon_phy_intr(struct skge_port *skge) | |||
2164 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ | 2211 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ |
2165 | switch (phystat & PHY_M_PS_PAUSE_MSK) { | 2212 | switch (phystat & PHY_M_PS_PAUSE_MSK) { |
2166 | case PHY_M_PS_PAUSE_MSK: | 2213 | case PHY_M_PS_PAUSE_MSK: |
2167 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 2214 | skge->flow_status = FLOW_STAT_SYMMETRIC; |
2168 | break; | 2215 | break; |
2169 | case PHY_M_PS_RX_P_EN: | 2216 | case PHY_M_PS_RX_P_EN: |
2170 | skge->flow_control = FLOW_MODE_REM_SEND; | 2217 | skge->flow_status = FLOW_STAT_REM_SEND; |
2171 | break; | 2218 | break; |
2172 | case PHY_M_PS_TX_P_EN: | 2219 | case PHY_M_PS_TX_P_EN: |
2173 | skge->flow_control = FLOW_MODE_LOC_SEND; | 2220 | skge->flow_status = FLOW_STAT_LOC_SEND; |
2174 | break; | 2221 | break; |
2175 | default: | 2222 | default: |
2176 | skge->flow_control = FLOW_MODE_NONE; | 2223 | skge->flow_status = FLOW_STAT_NONE; |
2177 | } | 2224 | } |
2178 | 2225 | ||
2179 | if (skge->flow_control == FLOW_MODE_NONE || | 2226 | if (skge->flow_status == FLOW_STAT_NONE || |
2180 | (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF)) | 2227 | (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF)) |
2181 | skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | 2228 | skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); |
2182 | else | 2229 | else |
@@ -3399,7 +3446,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, | |||
3399 | 3446 | ||
3400 | /* Auto speed and flow control */ | 3447 | /* Auto speed and flow control */ |
3401 | skge->autoneg = AUTONEG_ENABLE; | 3448 | skge->autoneg = AUTONEG_ENABLE; |
3402 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 3449 | skge->flow_control = FLOW_MODE_SYM_OR_REM; |
3403 | skge->duplex = -1; | 3450 | skge->duplex = -1; |
3404 | skge->speed = -1; | 3451 | skge->speed = -1; |
3405 | skge->advertising = skge_supported_modes(hw); | 3452 | skge->advertising = skge_supported_modes(hw); |