de2104x: fix TP link detection

Compex FreedomLine 32 PnP-PCI2 cards have only TP and BNC connectors but the
SROM contains AUI port too. When TP loses link, the driver switches to
non-existing AUI port (which reports that carrier is always present).

Connecting TP back generates LinkPass interrupt but de_media_interrupt() is
broken - it only updates the link state of currently connected media, ignoring
the fact that LinkPass and LinkFail bits of MacStatus register belong to the
TP port only (the chip documentation says that).

This patch changes de_media_interrupt() to switch media to TP when link goes
up (and media type is not locked) and also to update the link state only when
the TP port is used.

Also the NonselPortActive (and also SelPortActive) bits of SIAStatus register
need to be cleared (by writing 1) after reading or they're useless.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Ondrej Zary and committed by David S. Miller ca9a7835 b0255a02

+21 -2
+21 -2
drivers/net/tulip/de2104x.c
··· 243 243 NWayState = (1 << 14) | (1 << 13) | (1 << 12), 244 244 NWayRestart = (1 << 12), 245 245 NonselPortActive = (1 << 9), 246 + SelPortActive = (1 << 8), 246 247 LinkFailStatus = (1 << 2), 247 248 NetCxnErr = (1 << 1), 248 249 }; ··· 1067 1066 unsigned int carrier; 1068 1067 unsigned long flags; 1069 1068 1069 + /* clear port active bits */ 1070 + dw32(SIAStatus, NonselPortActive | SelPortActive); 1071 + 1070 1072 carrier = (status & NetCxnErr) ? 0 : 1; 1071 1073 1072 1074 if (carrier) { ··· 1164 1160 static void de_media_interrupt (struct de_private *de, u32 status) 1165 1161 { 1166 1162 if (status & LinkPass) { 1163 + /* Ignore if current media is AUI or BNC and we can't use TP */ 1164 + if ((de->media_type == DE_MEDIA_AUI || 1165 + de->media_type == DE_MEDIA_BNC) && 1166 + (de->media_lock || 1167 + !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))) 1168 + return; 1169 + /* If current media is not TP, change it to TP */ 1170 + if ((de->media_type == DE_MEDIA_AUI || 1171 + de->media_type == DE_MEDIA_BNC)) { 1172 + de->media_type = DE_MEDIA_TP_AUTO; 1173 + de_stop_rxtx(de); 1174 + de_set_media(de); 1175 + de_start_rxtx(de); 1176 + } 1167 1177 de_link_up(de); 1168 1178 mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); 1169 1179 return; 1170 1180 } 1171 1181 1172 1182 BUG_ON(!(status & LinkFail)); 1173 - 1174 - if (netif_carrier_ok(de->dev)) { 1183 + /* Mark the link as down only if current media is TP */ 1184 + if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI && 1185 + de->media_type != DE_MEDIA_BNC) { 1175 1186 de_link_down(de); 1176 1187 mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); 1177 1188 }