diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2011-08-19 09:58:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-20 13:34:27 -0400 |
commit | 5e5a7f371ffea4b5aeca60253f912e0b36391495 (patch) | |
tree | b14078de84b7bb81e4b1627531ea5a31657ce8a7 | |
parent | 6e01b20b21d6b2131f27a7c068ff71a7fbe58796 (diff) |
tg3: Pull phy int lpbk setup into separate func
This patch pulls out the internal phy loopback setup code into a
separate function. This cleans up the loopback test code and makes it
available for NETIF_F_LOOPBACK support later.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 149 |
1 files changed, 90 insertions, 59 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index abe2ec3c0022..08953b0999d2 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -6370,6 +6370,80 @@ static void tg3_mac_loopback(struct tg3 *tp, bool enable) | |||
6370 | udelay(40); | 6370 | udelay(40); |
6371 | } | 6371 | } |
6372 | 6372 | ||
6373 | static void tg3_phy_lpbk_set(struct tg3 *tp, u32 speed) | ||
6374 | { | ||
6375 | u32 val, bmcr, mac_mode; | ||
6376 | |||
6377 | tg3_phy_toggle_apd(tp, false); | ||
6378 | tg3_phy_toggle_automdix(tp, 0); | ||
6379 | |||
6380 | bmcr = BMCR_LOOPBACK | BMCR_FULLDPLX; | ||
6381 | switch (speed) { | ||
6382 | case SPEED_10: | ||
6383 | break; | ||
6384 | case SPEED_100: | ||
6385 | bmcr |= BMCR_SPEED100; | ||
6386 | break; | ||
6387 | case SPEED_1000: | ||
6388 | default: | ||
6389 | if (tp->phy_flags & TG3_PHYFLG_IS_FET) { | ||
6390 | speed = SPEED_100; | ||
6391 | bmcr |= BMCR_SPEED100; | ||
6392 | } else { | ||
6393 | speed = SPEED_1000; | ||
6394 | bmcr |= BMCR_SPEED1000; | ||
6395 | } | ||
6396 | } | ||
6397 | |||
6398 | tg3_writephy(tp, MII_BMCR, bmcr); | ||
6399 | |||
6400 | /* The write needs to be flushed for the FETs */ | ||
6401 | if (tp->phy_flags & TG3_PHYFLG_IS_FET) | ||
6402 | tg3_readphy(tp, MII_BMCR, &bmcr); | ||
6403 | |||
6404 | udelay(40); | ||
6405 | |||
6406 | if ((tp->phy_flags & TG3_PHYFLG_IS_FET) && | ||
6407 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { | ||
6408 | tg3_writephy(tp, MII_TG3_FET_PTEST, | ||
6409 | MII_TG3_FET_PTEST_FRC_TX_LINK | | ||
6410 | MII_TG3_FET_PTEST_FRC_TX_LOCK); | ||
6411 | |||
6412 | /* The write needs to be flushed for the AC131 */ | ||
6413 | tg3_readphy(tp, MII_TG3_FET_PTEST, &val); | ||
6414 | } | ||
6415 | |||
6416 | /* Reset to prevent losing 1st rx packet intermittently */ | ||
6417 | if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && | ||
6418 | tg3_flag(tp, 5780_CLASS)) { | ||
6419 | tw32_f(MAC_RX_MODE, RX_MODE_RESET); | ||
6420 | udelay(10); | ||
6421 | tw32_f(MAC_RX_MODE, tp->rx_mode); | ||
6422 | } | ||
6423 | |||
6424 | mac_mode = tp->mac_mode & | ||
6425 | ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); | ||
6426 | if (speed == SPEED_1000) | ||
6427 | mac_mode |= MAC_MODE_PORT_MODE_GMII; | ||
6428 | else | ||
6429 | mac_mode |= MAC_MODE_PORT_MODE_MII; | ||
6430 | |||
6431 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { | ||
6432 | u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK; | ||
6433 | |||
6434 | if (masked_phy_id == TG3_PHY_ID_BCM5401) | ||
6435 | mac_mode &= ~MAC_MODE_LINK_POLARITY; | ||
6436 | else if (masked_phy_id == TG3_PHY_ID_BCM5411) | ||
6437 | mac_mode |= MAC_MODE_LINK_POLARITY; | ||
6438 | |||
6439 | tg3_writephy(tp, MII_TG3_EXT_CTRL, | ||
6440 | MII_TG3_EXT_CTRL_LNK3_LED_MODE); | ||
6441 | } | ||
6442 | |||
6443 | tw32(MAC_MODE, mac_mode); | ||
6444 | udelay(40); | ||
6445 | } | ||
6446 | |||
6373 | static void tg3_set_loopback(struct net_device *dev, u32 features) | 6447 | static void tg3_set_loopback(struct net_device *dev, u32 features) |
6374 | { | 6448 | { |
6375 | struct tg3 *tp = netdev_priv(dev); | 6449 | struct tg3 *tp = netdev_priv(dev); |
@@ -11265,7 +11339,7 @@ static const u8 tg3_tso_header[] = { | |||
11265 | 11339 | ||
11266 | static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) | 11340 | static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) |
11267 | { | 11341 | { |
11268 | u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key; | 11342 | u32 rx_start_idx, rx_idx, tx_idx, opaque_key; |
11269 | u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val; | 11343 | u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val; |
11270 | u32 budget; | 11344 | u32 budget; |
11271 | struct sk_buff *skb, *rx_skb; | 11345 | struct sk_buff *skb, *rx_skb; |
@@ -11286,56 +11360,6 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode) | |||
11286 | } | 11360 | } |
11287 | coal_now = tnapi->coal_now | rnapi->coal_now; | 11361 | coal_now = tnapi->coal_now | rnapi->coal_now; |
11288 | 11362 | ||
11289 | if (loopback_mode != TG3_MAC_LOOPBACK) { | ||
11290 | if (tp->phy_flags & TG3_PHYFLG_IS_FET) { | ||
11291 | tg3_phy_fet_toggle_apd(tp, false); | ||
11292 | val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100; | ||
11293 | } else | ||
11294 | val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000; | ||
11295 | |||
11296 | tg3_phy_toggle_automdix(tp, 0); | ||
11297 | |||
11298 | tg3_writephy(tp, MII_BMCR, val); | ||
11299 | udelay(40); | ||
11300 | |||
11301 | mac_mode = tp->mac_mode & | ||
11302 | ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); | ||
11303 | if (tp->phy_flags & TG3_PHYFLG_IS_FET) { | ||
11304 | tg3_writephy(tp, MII_TG3_FET_PTEST, | ||
11305 | MII_TG3_FET_PTEST_FRC_TX_LINK | | ||
11306 | MII_TG3_FET_PTEST_FRC_TX_LOCK); | ||
11307 | /* The write needs to be flushed for the AC131 */ | ||
11308 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) | ||
11309 | tg3_readphy(tp, MII_TG3_FET_PTEST, &val); | ||
11310 | mac_mode |= MAC_MODE_PORT_MODE_MII; | ||
11311 | } else | ||
11312 | mac_mode |= MAC_MODE_PORT_MODE_GMII; | ||
11313 | |||
11314 | /* reset to prevent losing 1st rx packet intermittently */ | ||
11315 | if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) { | ||
11316 | tw32_f(MAC_RX_MODE, RX_MODE_RESET); | ||
11317 | udelay(10); | ||
11318 | tw32_f(MAC_RX_MODE, tp->rx_mode); | ||
11319 | } | ||
11320 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { | ||
11321 | u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK; | ||
11322 | if (masked_phy_id == TG3_PHY_ID_BCM5401) | ||
11323 | mac_mode &= ~MAC_MODE_LINK_POLARITY; | ||
11324 | else if (masked_phy_id == TG3_PHY_ID_BCM5411) | ||
11325 | mac_mode |= MAC_MODE_LINK_POLARITY; | ||
11326 | tg3_writephy(tp, MII_TG3_EXT_CTRL, | ||
11327 | MII_TG3_EXT_CTRL_LNK3_LED_MODE); | ||
11328 | } | ||
11329 | tw32(MAC_MODE, mac_mode); | ||
11330 | |||
11331 | /* Wait for link */ | ||
11332 | for (i = 0; i < 100; i++) { | ||
11333 | if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) | ||
11334 | break; | ||
11335 | mdelay(1); | ||
11336 | } | ||
11337 | } | ||
11338 | |||
11339 | err = -EIO; | 11363 | err = -EIO; |
11340 | 11364 | ||
11341 | tx_len = pktsz; | 11365 | tx_len = pktsz; |
@@ -11547,10 +11571,6 @@ static int tg3_test_loopback(struct tg3 *tp) | |||
11547 | tw32(i, 0x0); | 11571 | tw32(i, 0x0); |
11548 | } | 11572 | } |
11549 | 11573 | ||
11550 | /* Turn off gphy autopowerdown. */ | ||
11551 | if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) | ||
11552 | tg3_phy_toggle_apd(tp, false); | ||
11553 | |||
11554 | /* HW errata - mac loopback fails in some cases on 5780. | 11574 | /* HW errata - mac loopback fails in some cases on 5780. |
11555 | * Normal traffic and PHY loopback are not affected by | 11575 | * Normal traffic and PHY loopback are not affected by |
11556 | * errata. Also, the MAC loopback test is deprecated for | 11576 | * errata. Also, the MAC loopback test is deprecated for |
@@ -11574,6 +11594,17 @@ static int tg3_test_loopback(struct tg3 *tp) | |||
11574 | 11594 | ||
11575 | if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && | 11595 | if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) && |
11576 | !tg3_flag(tp, USE_PHYLIB)) { | 11596 | !tg3_flag(tp, USE_PHYLIB)) { |
11597 | int i; | ||
11598 | |||
11599 | tg3_phy_lpbk_set(tp, 0); | ||
11600 | |||
11601 | /* Wait for link */ | ||
11602 | for (i = 0; i < 100; i++) { | ||
11603 | if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP) | ||
11604 | break; | ||
11605 | mdelay(1); | ||
11606 | } | ||
11607 | |||
11577 | if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK)) | 11608 | if (tg3_run_loopback(tp, ETH_FRAME_LEN, TG3_PHY_LOOPBACK)) |
11578 | err |= TG3_STD_LOOPBACK_FAILED << | 11609 | err |= TG3_STD_LOOPBACK_FAILED << |
11579 | TG3_PHY_LOOPBACK_SHIFT; | 11610 | TG3_PHY_LOOPBACK_SHIFT; |
@@ -11585,11 +11616,11 @@ static int tg3_test_loopback(struct tg3 *tp) | |||
11585 | tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK)) | 11616 | tg3_run_loopback(tp, 9000 + ETH_HLEN, TG3_PHY_LOOPBACK)) |
11586 | err |= TG3_JMB_LOOPBACK_FAILED << | 11617 | err |= TG3_JMB_LOOPBACK_FAILED << |
11587 | TG3_PHY_LOOPBACK_SHIFT; | 11618 | TG3_PHY_LOOPBACK_SHIFT; |
11588 | } | ||
11589 | 11619 | ||
11590 | /* Re-enable gphy autopowerdown. */ | 11620 | /* Re-enable gphy autopowerdown. */ |
11591 | if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) | 11621 | if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD) |
11592 | tg3_phy_toggle_apd(tp, true); | 11622 | tg3_phy_toggle_apd(tp, true); |
11623 | } | ||
11593 | 11624 | ||
11594 | done: | 11625 | done: |
11595 | tp->phy_flags |= eee_cap; | 11626 | tp->phy_flags |= eee_cap; |