aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zary <linux@rainbow-software.org>2010-09-25 06:39:17 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-26 18:51:55 -0400
commitca9a783575d2affed30ef27a3427a7705527ddac (patch)
treecf4fb6545c85f1d7411877dadbab4db04eb3ec2c
parentb0255a02351b00ca55f4eb2588d05a5db9dd1a58 (diff)
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>
-rw-r--r--drivers/net/tulip/de2104x.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index a0be7c28c587..9124c5c638d8 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -243,6 +243,7 @@ enum {
243 NWayState = (1 << 14) | (1 << 13) | (1 << 12), 243 NWayState = (1 << 14) | (1 << 13) | (1 << 12),
244 NWayRestart = (1 << 12), 244 NWayRestart = (1 << 12),
245 NonselPortActive = (1 << 9), 245 NonselPortActive = (1 << 9),
246 SelPortActive = (1 << 8),
246 LinkFailStatus = (1 << 2), 247 LinkFailStatus = (1 << 2),
247 NetCxnErr = (1 << 1), 248 NetCxnErr = (1 << 1),
248}; 249};
@@ -1066,6 +1067,9 @@ static void de21041_media_timer (unsigned long data)
1066 unsigned int carrier; 1067 unsigned int carrier;
1067 unsigned long flags; 1068 unsigned long flags;
1068 1069
1070 /* clear port active bits */
1071 dw32(SIAStatus, NonselPortActive | SelPortActive);
1072
1069 carrier = (status & NetCxnErr) ? 0 : 1; 1073 carrier = (status & NetCxnErr) ? 0 : 1;
1070 1074
1071 if (carrier) { 1075 if (carrier) {
@@ -1160,14 +1164,29 @@ no_link_yet:
1160static void de_media_interrupt (struct de_private *de, u32 status) 1164static void de_media_interrupt (struct de_private *de, u32 status)
1161{ 1165{
1162 if (status & LinkPass) { 1166 if (status & LinkPass) {
1167 /* Ignore if current media is AUI or BNC and we can't use TP */
1168 if ((de->media_type == DE_MEDIA_AUI ||
1169 de->media_type == DE_MEDIA_BNC) &&
1170 (de->media_lock ||
1171 !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO)))
1172 return;
1173 /* If current media is not TP, change it to TP */
1174 if ((de->media_type == DE_MEDIA_AUI ||
1175 de->media_type == DE_MEDIA_BNC)) {
1176 de->media_type = DE_MEDIA_TP_AUTO;
1177 de_stop_rxtx(de);
1178 de_set_media(de);
1179 de_start_rxtx(de);
1180 }
1163 de_link_up(de); 1181 de_link_up(de);
1164 mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); 1182 mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK);
1165 return; 1183 return;
1166 } 1184 }
1167 1185
1168 BUG_ON(!(status & LinkFail)); 1186 BUG_ON(!(status & LinkFail));
1169 1187 /* Mark the link as down only if current media is TP */
1170 if (netif_carrier_ok(de->dev)) { 1188 if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI &&
1189 de->media_type != DE_MEDIA_BNC) {
1171 de_link_down(de); 1190 de_link_down(de);
1172 mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); 1191 mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
1173 } 1192 }