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