From 902827f6f3e795e979ab94359bc9f75ea05f539e Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Tue, 8 Apr 2008 11:51:17 +0000 Subject: 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 --- sys/dev/bge/if_bge.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sys/dev') diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 4cd179930773..b0238f7e16b8 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); } -- cgit v1.3