summaryrefslogtreecommitdiffstats
path: root/drivers/usb/net/pegasus.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2007-04-24 10:20:06 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-24 12:46:31 -0400
commitc43c49bd61fdb9bb085ddafcaadb17d06f95ec43 (patch)
treefc65c3603ca9e3f0819fbddd1cd4e8a66c39ad5b /drivers/usb/net/pegasus.c
parentb748d9e3b80dc7e6ce6bf7399f57964b99a4104c (diff)
downloadop-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.c17
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)
OpenPOWER on IntegriCloud