diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/e100.c | 93 |
1 files changed, 77 insertions, 16 deletions
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 861d2eeaa43c..0504db9ad643 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -167,7 +167,7 @@ | |||
167 | 167 | ||
168 | #define DRV_NAME "e100" | 168 | #define DRV_NAME "e100" |
169 | #define DRV_EXT "-NAPI" | 169 | #define DRV_EXT "-NAPI" |
170 | #define DRV_VERSION "3.5.23-k6"DRV_EXT | 170 | #define DRV_VERSION "3.5.24-k2"DRV_EXT |
171 | #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" | 171 | #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" |
172 | #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" | 172 | #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" |
173 | #define PFX DRV_NAME ": " | 173 | #define PFX DRV_NAME ": " |
@@ -240,6 +240,7 @@ static struct pci_device_id e100_id_table[] = { | |||
240 | INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), | 240 | INTEL_8255X_ETHERNET_DEVICE(0x1093, 7), |
241 | INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), | 241 | INTEL_8255X_ETHERNET_DEVICE(0x1094, 7), |
242 | INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), | 242 | INTEL_8255X_ETHERNET_DEVICE(0x1095, 7), |
243 | INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7), | ||
243 | INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), | 244 | INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), |
244 | INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), | 245 | INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), |
245 | INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), | 246 | INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), |
@@ -275,6 +276,7 @@ enum phy { | |||
275 | phy_82562_em = 0x032002A8, | 276 | phy_82562_em = 0x032002A8, |
276 | phy_82562_ek = 0x031002A8, | 277 | phy_82562_ek = 0x031002A8, |
277 | phy_82562_eh = 0x017002A8, | 278 | phy_82562_eh = 0x017002A8, |
279 | phy_82552_v = 0xd061004d, | ||
278 | phy_unknown = 0xFFFFFFFF, | 280 | phy_unknown = 0xFFFFFFFF, |
279 | }; | 281 | }; |
280 | 282 | ||
@@ -943,6 +945,22 @@ static int mdio_read(struct net_device *netdev, int addr, int reg) | |||
943 | 945 | ||
944 | static void mdio_write(struct net_device *netdev, int addr, int reg, int data) | 946 | static void mdio_write(struct net_device *netdev, int addr, int reg, int data) |
945 | { | 947 | { |
948 | struct nic *nic = netdev_priv(netdev); | ||
949 | |||
950 | if ((nic->phy == phy_82552_v) && (reg == MII_BMCR) && | ||
951 | (data & (BMCR_ANRESTART | BMCR_ANENABLE))) { | ||
952 | u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); | ||
953 | |||
954 | /* | ||
955 | * Workaround Si issue where sometimes the part will not | ||
956 | * autoneg to 100Mbps even when advertised. | ||
957 | */ | ||
958 | if (advert & ADVERTISE_100FULL) | ||
959 | data |= BMCR_SPEED100 | BMCR_FULLDPLX; | ||
960 | else if (advert & ADVERTISE_100HALF) | ||
961 | data |= BMCR_SPEED100; | ||
962 | } | ||
963 | |||
946 | mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); | 964 | mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data); |
947 | } | 965 | } |
948 | 966 | ||
@@ -1276,16 +1294,12 @@ static int e100_phy_init(struct nic *nic) | |||
1276 | if (addr == 32) | 1294 | if (addr == 32) |
1277 | return -EAGAIN; | 1295 | return -EAGAIN; |
1278 | 1296 | ||
1279 | /* Selected the phy and isolate the rest */ | 1297 | /* Isolate all the PHY ids */ |
1280 | for (addr = 0; addr < 32; addr++) { | 1298 | for (addr = 0; addr < 32; addr++) |
1281 | if (addr != nic->mii.phy_id) { | 1299 | mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); |
1282 | mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); | 1300 | /* Select the discovered PHY */ |
1283 | } else { | 1301 | bmcr &= ~BMCR_ISOLATE; |
1284 | bmcr = mdio_read(netdev, addr, MII_BMCR); | 1302 | mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); |
1285 | mdio_write(netdev, addr, MII_BMCR, | ||
1286 | bmcr & ~BMCR_ISOLATE); | ||
1287 | } | ||
1288 | } | ||
1289 | 1303 | ||
1290 | /* Get phy ID */ | 1304 | /* Get phy ID */ |
1291 | id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); | 1305 | id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); |
@@ -1303,7 +1317,18 @@ static int e100_phy_init(struct nic *nic) | |||
1303 | mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); | 1317 | mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); |
1304 | } | 1318 | } |
1305 | 1319 | ||
1306 | if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && | 1320 | if (nic->phy == phy_82552_v) { |
1321 | u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE); | ||
1322 | |||
1323 | /* Workaround Si not advertising flow-control during autoneg */ | ||
1324 | advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; | ||
1325 | mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert); | ||
1326 | |||
1327 | /* Reset for the above changes to take effect */ | ||
1328 | bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); | ||
1329 | bmcr |= BMCR_RESET; | ||
1330 | mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); | ||
1331 | } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && | ||
1307 | (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && | 1332 | (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && |
1308 | !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { | 1333 | !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { |
1309 | /* enable/disable MDI/MDI-X auto-switching. */ | 1334 | /* enable/disable MDI/MDI-X auto-switching. */ |
@@ -2134,6 +2159,9 @@ err_clean_rx: | |||
2134 | } | 2159 | } |
2135 | 2160 | ||
2136 | #define MII_LED_CONTROL 0x1B | 2161 | #define MII_LED_CONTROL 0x1B |
2162 | #define E100_82552_LED_OVERRIDE 0x19 | ||
2163 | #define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */ | ||
2164 | #define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */ | ||
2137 | static void e100_blink_led(unsigned long data) | 2165 | static void e100_blink_led(unsigned long data) |
2138 | { | 2166 | { |
2139 | struct nic *nic = (struct nic *)data; | 2167 | struct nic *nic = (struct nic *)data; |
@@ -2143,10 +2171,19 @@ static void e100_blink_led(unsigned long data) | |||
2143 | led_on_559 = 0x05, | 2171 | led_on_559 = 0x05, |
2144 | led_on_557 = 0x07, | 2172 | led_on_557 = 0x07, |
2145 | }; | 2173 | }; |
2174 | u16 led_reg = MII_LED_CONTROL; | ||
2175 | |||
2176 | if (nic->phy == phy_82552_v) { | ||
2177 | led_reg = E100_82552_LED_OVERRIDE; | ||
2146 | 2178 | ||
2147 | nic->leds = (nic->leds & led_on) ? led_off : | 2179 | nic->leds = (nic->leds == E100_82552_LED_ON) ? |
2148 | (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; | 2180 | E100_82552_LED_OFF : E100_82552_LED_ON; |
2149 | mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); | 2181 | } else { |
2182 | nic->leds = (nic->leds & led_on) ? led_off : | ||
2183 | (nic->mac < mac_82559_D101M) ? led_on_557 : | ||
2184 | led_on_559; | ||
2185 | } | ||
2186 | mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds); | ||
2150 | mod_timer(&nic->blink_timer, jiffies + HZ / 4); | 2187 | mod_timer(&nic->blink_timer, jiffies + HZ / 4); |
2151 | } | 2188 | } |
2152 | 2189 | ||
@@ -2375,13 +2412,15 @@ static void e100_diag_test(struct net_device *netdev, | |||
2375 | static int e100_phys_id(struct net_device *netdev, u32 data) | 2412 | static int e100_phys_id(struct net_device *netdev, u32 data) |
2376 | { | 2413 | { |
2377 | struct nic *nic = netdev_priv(netdev); | 2414 | struct nic *nic = netdev_priv(netdev); |
2415 | u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE : | ||
2416 | MII_LED_CONTROL; | ||
2378 | 2417 | ||
2379 | if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) | 2418 | if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) |
2380 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); | 2419 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); |
2381 | mod_timer(&nic->blink_timer, jiffies); | 2420 | mod_timer(&nic->blink_timer, jiffies); |
2382 | msleep_interruptible(data * 1000); | 2421 | msleep_interruptible(data * 1000); |
2383 | del_timer_sync(&nic->blink_timer); | 2422 | del_timer_sync(&nic->blink_timer); |
2384 | mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); | 2423 | mdio_write(netdev, nic->mii.phy_id, led_reg, 0); |
2385 | 2424 | ||
2386 | return 0; | 2425 | return 0; |
2387 | } | 2426 | } |
@@ -2686,6 +2725,9 @@ static void __devexit e100_remove(struct pci_dev *pdev) | |||
2686 | } | 2725 | } |
2687 | } | 2726 | } |
2688 | 2727 | ||
2728 | #define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ | ||
2729 | #define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ | ||
2730 | #define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ | ||
2689 | static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | 2731 | static int e100_suspend(struct pci_dev *pdev, pm_message_t state) |
2690 | { | 2732 | { |
2691 | struct net_device *netdev = pci_get_drvdata(pdev); | 2733 | struct net_device *netdev = pci_get_drvdata(pdev); |
@@ -2698,6 +2740,15 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2698 | pci_save_state(pdev); | 2740 | pci_save_state(pdev); |
2699 | 2741 | ||
2700 | if ((nic->flags & wol_magic) | e100_asf(nic)) { | 2742 | if ((nic->flags & wol_magic) | e100_asf(nic)) { |
2743 | /* enable reverse auto-negotiation */ | ||
2744 | if (nic->phy == phy_82552_v) { | ||
2745 | u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, | ||
2746 | E100_82552_SMARTSPEED); | ||
2747 | |||
2748 | mdio_write(netdev, nic->mii.phy_id, | ||
2749 | E100_82552_SMARTSPEED, smartspeed | | ||
2750 | E100_82552_REV_ANEG | E100_82552_ANEG_NOW); | ||
2751 | } | ||
2701 | if (pci_enable_wake(pdev, PCI_D3cold, true)) | 2752 | if (pci_enable_wake(pdev, PCI_D3cold, true)) |
2702 | pci_enable_wake(pdev, PCI_D3hot, true); | 2753 | pci_enable_wake(pdev, PCI_D3hot, true); |
2703 | } else { | 2754 | } else { |
@@ -2721,6 +2772,16 @@ static int e100_resume(struct pci_dev *pdev) | |||
2721 | /* ack any pending wake events, disable PME */ | 2772 | /* ack any pending wake events, disable PME */ |
2722 | pci_enable_wake(pdev, 0, 0); | 2773 | pci_enable_wake(pdev, 0, 0); |
2723 | 2774 | ||
2775 | /* disbale reverse auto-negotiation */ | ||
2776 | if (nic->phy == phy_82552_v) { | ||
2777 | u16 smartspeed = mdio_read(netdev, nic->mii.phy_id, | ||
2778 | E100_82552_SMARTSPEED); | ||
2779 | |||
2780 | mdio_write(netdev, nic->mii.phy_id, | ||
2781 | E100_82552_SMARTSPEED, | ||
2782 | smartspeed & ~(E100_82552_REV_ANEG)); | ||
2783 | } | ||
2784 | |||
2724 | netif_device_attach(netdev); | 2785 | netif_device_attach(netdev); |
2725 | if (netif_running(netdev)) | 2786 | if (netif_running(netdev)) |
2726 | e100_up(nic); | 2787 | e100_up(nic); |