diff options
author | Michael Chan <mchan@broadcom.com> | 2006-11-19 17:07:28 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:24:18 -0500 |
commit | 80be44348e30b68d2d8c5b6d1b7e53f2c5659134 (patch) | |
tree | 6bf7e3c6f9dd11f8ee90ec90a1e7df98f741dd02 | |
parent | 7510873d8659f4192cb5b3327f748e401d216399 (diff) |
[BNX2]: Improve SerDes handling.
1. Add support for 2.5Gbps forced speed setting.
2. Remove a long udelay() loop and change to msleep().
3. Other misc. SerDes fixes.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/bnx2.c | 60 | ||||
-rw-r--r-- | drivers/net/bnx2.h | 2 |
2 files changed, 41 insertions, 21 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b60e45d1ce3d..9b391cf80a32 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -860,7 +860,7 @@ bnx2_set_link(struct bnx2 *bp) | |||
860 | u32 bmsr; | 860 | u32 bmsr; |
861 | u8 link_up; | 861 | u8 link_up; |
862 | 862 | ||
863 | if (bp->loopback == MAC_LOOPBACK) { | 863 | if (bp->loopback == MAC_LOOPBACK || bp->loopback == PHY_LOOPBACK) { |
864 | bp->link_up = 1; | 864 | bp->link_up = 1; |
865 | return 0; | 865 | return 0; |
866 | } | 866 | } |
@@ -902,6 +902,7 @@ bnx2_set_link(struct bnx2 *bp) | |||
902 | u32 bmcr; | 902 | u32 bmcr; |
903 | 903 | ||
904 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | 904 | bnx2_read_phy(bp, MII_BMCR, &bmcr); |
905 | bmcr &= ~BCM5708S_BMCR_FORCE_2500; | ||
905 | if (!(bmcr & BMCR_ANENABLE)) { | 906 | if (!(bmcr & BMCR_ANENABLE)) { |
906 | bnx2_write_phy(bp, MII_BMCR, bmcr | | 907 | bnx2_write_phy(bp, MII_BMCR, bmcr | |
907 | BMCR_ANENABLE); | 908 | BMCR_ANENABLE); |
@@ -988,7 +989,21 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
988 | u32 new_bmcr; | 989 | u32 new_bmcr; |
989 | int force_link_down = 0; | 990 | int force_link_down = 0; |
990 | 991 | ||
991 | if (CHIP_NUM(bp) == CHIP_NUM_5708) { | 992 | bnx2_read_phy(bp, MII_ADVERTISE, &adv); |
993 | adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); | ||
994 | |||
995 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | ||
996 | new_bmcr = bmcr & ~(BMCR_ANENABLE | BCM5708S_BMCR_FORCE_2500); | ||
997 | new_bmcr |= BMCR_SPEED1000; | ||
998 | if (bp->req_line_speed == SPEED_2500) { | ||
999 | new_bmcr |= BCM5708S_BMCR_FORCE_2500; | ||
1000 | bnx2_read_phy(bp, BCM5708S_UP1, &up1); | ||
1001 | if (!(up1 & BCM5708S_UP1_2G5)) { | ||
1002 | up1 |= BCM5708S_UP1_2G5; | ||
1003 | bnx2_write_phy(bp, BCM5708S_UP1, up1); | ||
1004 | force_link_down = 1; | ||
1005 | } | ||
1006 | } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { | ||
992 | bnx2_read_phy(bp, BCM5708S_UP1, &up1); | 1007 | bnx2_read_phy(bp, BCM5708S_UP1, &up1); |
993 | if (up1 & BCM5708S_UP1_2G5) { | 1008 | if (up1 & BCM5708S_UP1_2G5) { |
994 | up1 &= ~BCM5708S_UP1_2G5; | 1009 | up1 &= ~BCM5708S_UP1_2G5; |
@@ -997,12 +1012,6 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
997 | } | 1012 | } |
998 | } | 1013 | } |
999 | 1014 | ||
1000 | bnx2_read_phy(bp, MII_ADVERTISE, &adv); | ||
1001 | adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); | ||
1002 | |||
1003 | bnx2_read_phy(bp, MII_BMCR, &bmcr); | ||
1004 | new_bmcr = bmcr & ~BMCR_ANENABLE; | ||
1005 | new_bmcr |= BMCR_SPEED1000; | ||
1006 | if (bp->req_duplex == DUPLEX_FULL) { | 1015 | if (bp->req_duplex == DUPLEX_FULL) { |
1007 | adv |= ADVERTISE_1000XFULL; | 1016 | adv |= ADVERTISE_1000XFULL; |
1008 | new_bmcr |= BMCR_FULLDPLX; | 1017 | new_bmcr |= BMCR_FULLDPLX; |
@@ -1023,6 +1032,7 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
1023 | bp->link_up = 0; | 1032 | bp->link_up = 0; |
1024 | netif_carrier_off(bp->dev); | 1033 | netif_carrier_off(bp->dev); |
1025 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); | 1034 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); |
1035 | bnx2_report_link(bp); | ||
1026 | } | 1036 | } |
1027 | bnx2_write_phy(bp, MII_ADVERTISE, adv); | 1037 | bnx2_write_phy(bp, MII_ADVERTISE, adv); |
1028 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); | 1038 | bnx2_write_phy(bp, MII_BMCR, new_bmcr); |
@@ -1048,12 +1058,10 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) | |||
1048 | if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { | 1058 | if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { |
1049 | /* Force a link down visible on the other side */ | 1059 | /* Force a link down visible on the other side */ |
1050 | if (bp->link_up) { | 1060 | if (bp->link_up) { |
1051 | int i; | ||
1052 | |||
1053 | bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); | 1061 | bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); |
1054 | for (i = 0; i < 110; i++) { | 1062 | spin_unlock_bh(&bp->phy_lock); |
1055 | udelay(100); | 1063 | msleep(20); |
1056 | } | 1064 | spin_lock_bh(&bp->phy_lock); |
1057 | } | 1065 | } |
1058 | 1066 | ||
1059 | bnx2_write_phy(bp, MII_ADVERTISE, new_adv); | 1067 | bnx2_write_phy(bp, MII_ADVERTISE, new_adv); |
@@ -1397,7 +1405,7 @@ bnx2_set_phy_loopback(struct bnx2 *bp) | |||
1397 | for (i = 0; i < 10; i++) { | 1405 | for (i = 0; i < 10; i++) { |
1398 | if (bnx2_test_link(bp) == 0) | 1406 | if (bnx2_test_link(bp) == 0) |
1399 | break; | 1407 | break; |
1400 | udelay(10); | 1408 | msleep(100); |
1401 | } | 1409 | } |
1402 | 1410 | ||
1403 | mac_mode = REG_RD(bp, BNX2_EMAC_MODE); | 1411 | mac_mode = REG_RD(bp, BNX2_EMAC_MODE); |
@@ -3713,7 +3721,9 @@ bnx2_init_nic(struct bnx2 *bp) | |||
3713 | if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0) | 3721 | if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0) |
3714 | return rc; | 3722 | return rc; |
3715 | 3723 | ||
3724 | spin_lock_bh(&bp->phy_lock); | ||
3716 | bnx2_init_phy(bp); | 3725 | bnx2_init_phy(bp); |
3726 | spin_unlock_bh(&bp->phy_lock); | ||
3717 | bnx2_set_link(bp); | 3727 | bnx2_set_link(bp); |
3718 | return 0; | 3728 | return 0; |
3719 | } | 3729 | } |
@@ -3953,7 +3963,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) | |||
3953 | bnx2_set_mac_loopback(bp); | 3963 | bnx2_set_mac_loopback(bp); |
3954 | } | 3964 | } |
3955 | else if (loopback_mode == BNX2_PHY_LOOPBACK) { | 3965 | else if (loopback_mode == BNX2_PHY_LOOPBACK) { |
3956 | bp->loopback = 0; | 3966 | bp->loopback = PHY_LOOPBACK; |
3957 | bnx2_set_phy_loopback(bp); | 3967 | bnx2_set_phy_loopback(bp); |
3958 | } | 3968 | } |
3959 | else | 3969 | else |
@@ -4744,10 +4754,14 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
4744 | } | 4754 | } |
4745 | else { | 4755 | else { |
4746 | if (bp->phy_flags & PHY_SERDES_FLAG) { | 4756 | if (bp->phy_flags & PHY_SERDES_FLAG) { |
4747 | if ((cmd->speed != SPEED_1000) || | 4757 | if ((cmd->speed != SPEED_1000 && |
4748 | (cmd->duplex != DUPLEX_FULL)) { | 4758 | cmd->speed != SPEED_2500) || |
4759 | (cmd->duplex != DUPLEX_FULL)) | ||
4760 | return -EINVAL; | ||
4761 | |||
4762 | if (cmd->speed == SPEED_2500 && | ||
4763 | !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) | ||
4749 | return -EINVAL; | 4764 | return -EINVAL; |
4750 | } | ||
4751 | } | 4765 | } |
4752 | else if (cmd->speed == SPEED_1000) { | 4766 | else if (cmd->speed == SPEED_1000) { |
4753 | return -EINVAL; | 4767 | return -EINVAL; |
@@ -5289,6 +5303,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) | |||
5289 | 5303 | ||
5290 | memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); | 5304 | memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); |
5291 | if (etest->flags & ETH_TEST_FL_OFFLINE) { | 5305 | if (etest->flags & ETH_TEST_FL_OFFLINE) { |
5306 | int i; | ||
5307 | |||
5292 | bnx2_netif_stop(bp); | 5308 | bnx2_netif_stop(bp); |
5293 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); | 5309 | bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); |
5294 | bnx2_free_skbs(bp); | 5310 | bnx2_free_skbs(bp); |
@@ -5313,9 +5329,11 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) | |||
5313 | } | 5329 | } |
5314 | 5330 | ||
5315 | /* wait for link up */ | 5331 | /* wait for link up */ |
5316 | msleep_interruptible(3000); | 5332 | for (i = 0; i < 7; i++) { |
5317 | if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG)) | 5333 | if (bp->link_up) |
5318 | msleep_interruptible(4000); | 5334 | break; |
5335 | msleep_interruptible(1000); | ||
5336 | } | ||
5319 | } | 5337 | } |
5320 | 5338 | ||
5321 | if (bnx2_test_nvram(bp) != 0) { | 5339 | if (bnx2_test_nvram(bp) != 0) { |
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index ca31904893ea..78ff09d70de4 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h | |||
@@ -3696,6 +3696,8 @@ struct l2_fhdr { | |||
3696 | 3696 | ||
3697 | /* 5708 Serdes PHY registers */ | 3697 | /* 5708 Serdes PHY registers */ |
3698 | 3698 | ||
3699 | #define BCM5708S_BMCR_FORCE_2500 0x20 | ||
3700 | |||
3699 | #define BCM5708S_UP1 0xb | 3701 | #define BCM5708S_UP1 0xb |
3700 | 3702 | ||
3701 | #define BCM5708S_UP1_2G5 0x1 | 3703 | #define BCM5708S_UP1_2G5 0x1 |