diff options
author | Michael Chan <mchan@broadcom.com> | 2007-10-10 19:16:31 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:55:57 -0400 |
commit | 489310a440e606512b1fd79d8562d1da6b715448 (patch) | |
tree | 5273f818aa52a57c7ee4890f4f974f8a91b547bf /drivers | |
parent | 631a6698d09e57cadc069914d613899609a0ae83 (diff) |
[BNX2]: Fix remote PHY media detection problems.
The remote PHY media type and link status can change between
->probe() and ->open(). For correct operation, we need to get the
new status again during ->open().
The ethtool link test and loopback test are also fixed to work with
remote PHY. PHY loopback is simply skipped when remote PHY is
present.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/bnx2.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0e4928c751ff..21493e0cbd42 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -3776,12 +3776,6 @@ bnx2_init_remote_phy(struct bnx2 *bp) | |||
3776 | return; | 3776 | return; |
3777 | 3777 | ||
3778 | if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) { | 3778 | if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) { |
3779 | if (netif_running(bp->dev)) { | ||
3780 | val = BNX2_DRV_ACK_CAP_SIGNATURE | | ||
3781 | BNX2_FW_CAP_REMOTE_PHY_CAPABLE; | ||
3782 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB, | ||
3783 | val); | ||
3784 | } | ||
3785 | bp->phy_flags |= REMOTE_PHY_CAP_FLAG; | 3779 | bp->phy_flags |= REMOTE_PHY_CAP_FLAG; |
3786 | 3780 | ||
3787 | val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); | 3781 | val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); |
@@ -3789,6 +3783,22 @@ bnx2_init_remote_phy(struct bnx2 *bp) | |||
3789 | bp->phy_port = PORT_FIBRE; | 3783 | bp->phy_port = PORT_FIBRE; |
3790 | else | 3784 | else |
3791 | bp->phy_port = PORT_TP; | 3785 | bp->phy_port = PORT_TP; |
3786 | |||
3787 | if (netif_running(bp->dev)) { | ||
3788 | u32 sig; | ||
3789 | |||
3790 | if (val & BNX2_LINK_STATUS_LINK_UP) { | ||
3791 | bp->link_up = 1; | ||
3792 | netif_carrier_on(bp->dev); | ||
3793 | } else { | ||
3794 | bp->link_up = 0; | ||
3795 | netif_carrier_off(bp->dev); | ||
3796 | } | ||
3797 | sig = BNX2_DRV_ACK_CAP_SIGNATURE | | ||
3798 | BNX2_FW_CAP_REMOTE_PHY_CAPABLE; | ||
3799 | REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB, | ||
3800 | sig); | ||
3801 | } | ||
3792 | } | 3802 | } |
3793 | } | 3803 | } |
3794 | 3804 | ||
@@ -3797,6 +3807,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) | |||
3797 | { | 3807 | { |
3798 | u32 val; | 3808 | u32 val; |
3799 | int i, rc = 0; | 3809 | int i, rc = 0; |
3810 | u8 old_port; | ||
3800 | 3811 | ||
3801 | /* Wait for the current PCI transaction to complete before | 3812 | /* Wait for the current PCI transaction to complete before |
3802 | * issuing a reset. */ | 3813 | * issuing a reset. */ |
@@ -3875,8 +3886,9 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) | |||
3875 | return rc; | 3886 | return rc; |
3876 | 3887 | ||
3877 | spin_lock_bh(&bp->phy_lock); | 3888 | spin_lock_bh(&bp->phy_lock); |
3889 | old_port = bp->phy_port; | ||
3878 | bnx2_init_remote_phy(bp); | 3890 | bnx2_init_remote_phy(bp); |
3879 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | 3891 | if ((bp->phy_flags & REMOTE_PHY_CAP_FLAG) && old_port != bp->phy_port) |
3880 | bnx2_set_default_remote_link(bp); | 3892 | bnx2_set_default_remote_link(bp); |
3881 | spin_unlock_bh(&bp->phy_lock); | 3893 | spin_unlock_bh(&bp->phy_lock); |
3882 | 3894 | ||
@@ -4565,6 +4577,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) | |||
4565 | bnx2_set_mac_loopback(bp); | 4577 | bnx2_set_mac_loopback(bp); |
4566 | } | 4578 | } |
4567 | else if (loopback_mode == BNX2_PHY_LOOPBACK) { | 4579 | else if (loopback_mode == BNX2_PHY_LOOPBACK) { |
4580 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) | ||
4581 | return 0; | ||
4582 | |||
4568 | bp->loopback = PHY_LOOPBACK; | 4583 | bp->loopback = PHY_LOOPBACK; |
4569 | bnx2_set_phy_loopback(bp); | 4584 | bnx2_set_phy_loopback(bp); |
4570 | } | 4585 | } |
@@ -4733,6 +4748,11 @@ bnx2_test_link(struct bnx2 *bp) | |||
4733 | { | 4748 | { |
4734 | u32 bmsr; | 4749 | u32 bmsr; |
4735 | 4750 | ||
4751 | if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { | ||
4752 | if (bp->link_up) | ||
4753 | return 0; | ||
4754 | return -ENODEV; | ||
4755 | } | ||
4736 | spin_lock_bh(&bp->phy_lock); | 4756 | spin_lock_bh(&bp->phy_lock); |
4737 | bnx2_enable_bmsr1(bp); | 4757 | bnx2_enable_bmsr1(bp); |
4738 | bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); | 4758 | bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr); |