diff options
Diffstat (limited to 'drivers/net/tulip/de2104x.c')
| -rw-r--r-- | drivers/net/tulip/de2104x.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 5efa57757a2c..6888e3d41462 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 | }; |
| @@ -363,7 +364,9 @@ static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, }; | |||
| 363 | 364 | ||
| 364 | /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ | 365 | /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ |
| 365 | static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; | 366 | static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; |
| 366 | static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; | 367 | static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; |
| 368 | /* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */ | ||
| 369 | static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; | ||
| 367 | static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; | 370 | static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; |
| 368 | 371 | ||
| 369 | 372 | ||
| @@ -1064,6 +1067,9 @@ static void de21041_media_timer (unsigned long data) | |||
| 1064 | unsigned int carrier; | 1067 | unsigned int carrier; |
| 1065 | unsigned long flags; | 1068 | unsigned long flags; |
| 1066 | 1069 | ||
| 1070 | /* clear port active bits */ | ||
| 1071 | dw32(SIAStatus, NonselPortActive | SelPortActive); | ||
| 1072 | |||
| 1067 | carrier = (status & NetCxnErr) ? 0 : 1; | 1073 | carrier = (status & NetCxnErr) ? 0 : 1; |
| 1068 | 1074 | ||
| 1069 | if (carrier) { | 1075 | if (carrier) { |
| @@ -1158,14 +1164,29 @@ no_link_yet: | |||
| 1158 | static void de_media_interrupt (struct de_private *de, u32 status) | 1164 | static void de_media_interrupt (struct de_private *de, u32 status) |
| 1159 | { | 1165 | { |
| 1160 | 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 | } | ||
| 1161 | de_link_up(de); | 1181 | de_link_up(de); |
| 1162 | mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); | 1182 | mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); |
| 1163 | return; | 1183 | return; |
| 1164 | } | 1184 | } |
| 1165 | 1185 | ||
| 1166 | BUG_ON(!(status & LinkFail)); | 1186 | BUG_ON(!(status & LinkFail)); |
| 1167 | 1187 | /* Mark the link as down only if current media is TP */ | |
| 1168 | 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) { | ||
| 1169 | de_link_down(de); | 1190 | de_link_down(de); |
| 1170 | mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); | 1191 | mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); |
| 1171 | } | 1192 | } |
| @@ -1229,6 +1250,7 @@ static void de_adapter_sleep (struct de_private *de) | |||
| 1229 | if (de->de21040) | 1250 | if (de->de21040) |
| 1230 | return; | 1251 | return; |
| 1231 | 1252 | ||
| 1253 | dw32(CSR13, 0); /* Reset phy */ | ||
| 1232 | pci_read_config_dword(de->pdev, PCIPM, &pmctl); | 1254 | pci_read_config_dword(de->pdev, PCIPM, &pmctl); |
| 1233 | pmctl |= PM_Sleep; | 1255 | pmctl |= PM_Sleep; |
| 1234 | pci_write_config_dword(de->pdev, PCIPM, pmctl); | 1256 | pci_write_config_dword(de->pdev, PCIPM, pmctl); |
| @@ -1574,12 +1596,15 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) | |||
| 1574 | return 0; /* nothing to change */ | 1596 | return 0; /* nothing to change */ |
| 1575 | 1597 | ||
| 1576 | de_link_down(de); | 1598 | de_link_down(de); |
| 1599 | mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); | ||
| 1577 | de_stop_rxtx(de); | 1600 | de_stop_rxtx(de); |
| 1578 | 1601 | ||
| 1579 | de->media_type = new_media; | 1602 | de->media_type = new_media; |
| 1580 | de->media_lock = media_lock; | 1603 | de->media_lock = media_lock; |
| 1581 | de->media_advertise = ecmd->advertising; | 1604 | de->media_advertise = ecmd->advertising; |
| 1582 | de_set_media(de); | 1605 | de_set_media(de); |
| 1606 | if (netif_running(de->dev)) | ||
| 1607 | de_start_rxtx(de); | ||
| 1583 | 1608 | ||
| 1584 | return 0; | 1609 | return 0; |
| 1585 | } | 1610 | } |
| @@ -1911,8 +1936,14 @@ fill_defaults: | |||
| 1911 | for (i = 0; i < DE_MAX_MEDIA; i++) { | 1936 | for (i = 0; i < DE_MAX_MEDIA; i++) { |
| 1912 | if (de->media[i].csr13 == 0xffff) | 1937 | if (de->media[i].csr13 == 0xffff) |
| 1913 | de->media[i].csr13 = t21041_csr13[i]; | 1938 | de->media[i].csr13 = t21041_csr13[i]; |
| 1914 | if (de->media[i].csr14 == 0xffff) | 1939 | if (de->media[i].csr14 == 0xffff) { |
| 1915 | de->media[i].csr14 = t21041_csr14[i]; | 1940 | /* autonegotiation is broken at least on some chip |
| 1941 | revisions - rev. 0x21 works, 0x11 does not */ | ||
| 1942 | if (de->pdev->revision < 0x20) | ||
| 1943 | de->media[i].csr14 = t21041_csr14_brk[i]; | ||
| 1944 | else | ||
| 1945 | de->media[i].csr14 = t21041_csr14[i]; | ||
| 1946 | } | ||
| 1916 | if (de->media[i].csr15 == 0xffff) | 1947 | if (de->media[i].csr15 == 0xffff) |
| 1917 | de->media[i].csr15 = t21041_csr15[i]; | 1948 | de->media[i].csr15 = t21041_csr15[i]; |
| 1918 | } | 1949 | } |
| @@ -2158,6 +2189,8 @@ static int de_resume (struct pci_dev *pdev) | |||
| 2158 | dev_err(&dev->dev, "pci_enable_device failed in resume\n"); | 2189 | dev_err(&dev->dev, "pci_enable_device failed in resume\n"); |
| 2159 | goto out; | 2190 | goto out; |
| 2160 | } | 2191 | } |
| 2192 | pci_set_master(pdev); | ||
| 2193 | de_init_rings(de); | ||
| 2161 | de_init_hw(de); | 2194 | de_init_hw(de); |
| 2162 | out_attach: | 2195 | out_attach: |
| 2163 | netif_device_attach(dev); | 2196 | netif_device_attach(dev); |
