diff options
author | Dan Williams <dcbw@redhat.com> | 2007-04-24 10:20:06 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-24 12:46:31 -0400 |
commit | c43c49bd61fdb9bb085ddafcaadb17d06f95ec43 (patch) | |
tree | fc65c3603ca9e3f0819fbddd1cd4e8a66c39ad5b /drivers/usb/net/pegasus.c | |
parent | b748d9e3b80dc7e6ce6bf7399f57964b99a4104c (diff) | |
download | op-kernel-dev-c43c49bd61fdb9bb085ddafcaadb17d06f95ec43.zip op-kernel-dev-c43c49bd61fdb9bb085ddafcaadb17d06f95ec43.tar.gz |
usb-net/pegasus: fix pegasus carrier detection
Broken by 4a1728a28a193aa388900714bbb1f375e08a6d8e which switched the
return semantics of read_mii_word() but didn't fix usage of
read_mii_word() to conform to the new semantics.
Setting carrier to off based on the NO_CARRIER flag is also incorrect as
that flag only triggers on TX failure and therefore isn't correct when
no frames are being transmitted. Since there is already a 2*HZ MII
carrier check going on, defer to that.
Add a TRUST_LINK_STATUS feature flag for adapters where the LINK_STATUS
flag is actually correct, and use that rather than the NO_CARRIER flag.
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/usb/net/pegasus.c')
-rw-r--r-- | drivers/usb/net/pegasus.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index d48c024..6d12961 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -316,6 +316,7 @@ static int update_eth_regs_async(pegasus_t * pegasus) return ret; } +/* Returns 0 on success, error on failure */ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) { int i; @@ -847,10 +848,16 @@ static void intr_callback(struct urb *urb) * d[0].NO_CARRIER kicks in only with failed TX. * ... so monitoring with MII may be safest. */ - if (d[0] & NO_CARRIER) - netif_carrier_off(net); - else - netif_carrier_on(net); + if (pegasus->features & TRUST_LINK_STATUS) { + if (d[5] & LINK_STATUS) + netif_carrier_on(net); + else + netif_carrier_off(net); + } else { + /* Never set carrier _on_ based on ! NO_CARRIER */ + if (d[0] & NO_CARRIER) + netif_carrier_off(net); + } /* bytes 3-4 == rx_lostpkt, reg 2E/2F */ pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4]; @@ -950,7 +957,7 @@ static void set_carrier(struct net_device *net) pegasus_t *pegasus = netdev_priv(net); u16 tmp; - if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) + if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) return; if (tmp & BMSR_LSTATUS) |