summaryrefslogtreecommitdiffstats
path: root/sys/dev/bge
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2008-04-08 11:51:17 +0000
committerbz <bz@FreeBSD.org>2008-04-08 11:51:17 +0000
commite72139652ffb40042cac781213899ed928ac466a (patch)
tree91b5da26bca032545419babfafbf63fdc46e728c /sys/dev/bge
parentbb2376b552530f062f337d52a79f0a1b43fc9070 (diff)
downloadFreeBSD-src-e72139652ffb40042cac781213899ed928ac466a.zip
FreeBSD-src-e72139652ffb40042cac781213899ed928ac466a.tar.gz
In some situations we were not clearing pending link state attentions.
Because of this we were not getting further interrupts for link state changes, thus never went into iface UP state and thus could not transmit. The only way out of this was an incoming packet generating an rx interrupt and making us call into bge_link_upd. Up to rev. 1.101, in bge_start_locked, we only returned instantly if there was 'no link AND nothing queued for tx'. So with a packet queued for tx, we hit the register scrubbing at the end of bge_start_locked and were out fine. We simply lost a packet or two but got the interrupts need to get into UP state. With rev. 1.102 this was turned into 'if there is no link OR there is nothing to send' (correct behaviour) and as long as there is no link we never hit the register scrubbing and consequently never got the link UP. What we do now is force an interrupt at the end of bge_ifmedia_upd_locked so we will call bge_link_upd, clear the link state attention and get further interrupts. This helps to get the iface UP on an idle network or at least to get it UP faster not depending on an rx intr anymore. In case you could not get a DHCP lease or it took very long, it was because of this. It is unknown which chips are affected by this. ASIC rev. 0x2003 was the most popular trouble candidate. At least the fiber cards should have been working fine. Which register to scrub is currently under discussion. The comitted solution was tested and found to work for a lot of setups. It might not help with MSI. The reason why we end up in such a situation is entirely unknown. PR: kern/111804 Tested by: phk, scottl at Y! MFC after: 14 days
Diffstat (limited to 'sys/dev/bge')
-rw-r--r--sys/dev/bge/if_bge.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 4cd1799..b0238f7 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -3795,6 +3795,23 @@ bge_ifmedia_upd_locked(struct ifnet *ifp)
}
mii_mediachg(mii);
+ /*
+ * Force an interrupt so that we will call bge_link_upd
+ * if needed and clear any pending link state attention.
+ * Without this we are not getting any further interrupts
+ * for link state changes and thus will not UP the link and
+ * not be able to send in bge_start_locked. The only
+ * way to get things working was to receive a packet and
+ * get an RX intr.
+ * bge_tick should help for fiber cards and we might not
+ * need to do this here if BGE_FLAG_TBI is set but as
+ * we poll for fiber anyway it should not harm.
+ */
+ BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET);
+#ifdef notyet
+ BGE_SETBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ATTN);
+#endif
+
return (0);
}
OpenPOWER on IntegriCloud