|
@@ -167,7 +167,7 @@
|
|
|
|
|
|
#define DRV_NAME "e100"
|
|
#define DRV_NAME "e100"
|
|
#define DRV_EXT "-NAPI"
|
|
#define DRV_EXT "-NAPI"
|
|
-#define DRV_VERSION "3.5.23-k6"DRV_EXT
|
|
|
|
|
|
+#define DRV_VERSION "3.5.24-k2"DRV_EXT
|
|
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
|
|
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
|
|
#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
|
|
#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
|
|
#define PFX DRV_NAME ": "
|
|
#define PFX DRV_NAME ": "
|
|
@@ -240,6 +240,7 @@ static struct pci_device_id e100_id_table[] = {
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
|
|
|
|
+ INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
|
|
INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
|
|
@@ -275,6 +276,7 @@ enum phy {
|
|
phy_82562_em = 0x032002A8,
|
|
phy_82562_em = 0x032002A8,
|
|
phy_82562_ek = 0x031002A8,
|
|
phy_82562_ek = 0x031002A8,
|
|
phy_82562_eh = 0x017002A8,
|
|
phy_82562_eh = 0x017002A8,
|
|
|
|
+ phy_82552_v = 0xd061004d,
|
|
phy_unknown = 0xFFFFFFFF,
|
|
phy_unknown = 0xFFFFFFFF,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -943,6 +945,22 @@ static int mdio_read(struct net_device *netdev, int addr, int reg)
|
|
|
|
|
|
static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
|
|
static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
|
|
{
|
|
{
|
|
|
|
+ struct nic *nic = netdev_priv(netdev);
|
|
|
|
+
|
|
|
|
+ if ((nic->phy == phy_82552_v) && (reg == MII_BMCR) &&
|
|
|
|
+ (data & (BMCR_ANRESTART | BMCR_ANENABLE))) {
|
|
|
|
+ u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Workaround Si issue where sometimes the part will not
|
|
|
|
+ * autoneg to 100Mbps even when advertised.
|
|
|
|
+ */
|
|
|
|
+ if (advert & ADVERTISE_100FULL)
|
|
|
|
+ data |= BMCR_SPEED100 | BMCR_FULLDPLX;
|
|
|
|
+ else if (advert & ADVERTISE_100HALF)
|
|
|
|
+ data |= BMCR_SPEED100;
|
|
|
|
+ }
|
|
|
|
+
|
|
mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
|
|
mdio_ctrl(netdev_priv(netdev), addr, mdi_write, reg, data);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1276,16 +1294,12 @@ static int e100_phy_init(struct nic *nic)
|
|
if (addr == 32)
|
|
if (addr == 32)
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
|
|
|
|
- /* Selected the phy and isolate the rest */
|
|
|
|
- for (addr = 0; addr < 32; addr++) {
|
|
|
|
- if (addr != nic->mii.phy_id) {
|
|
|
|
- mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
|
|
|
|
- } else {
|
|
|
|
- bmcr = mdio_read(netdev, addr, MII_BMCR);
|
|
|
|
- mdio_write(netdev, addr, MII_BMCR,
|
|
|
|
- bmcr & ~BMCR_ISOLATE);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ /* Isolate all the PHY ids */
|
|
|
|
+ for (addr = 0; addr < 32; addr++)
|
|
|
|
+ mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
|
|
|
|
+ /* Select the discovered PHY */
|
|
|
|
+ bmcr &= ~BMCR_ISOLATE;
|
|
|
|
+ mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
|
|
|
|
|
|
/* Get phy ID */
|
|
/* Get phy ID */
|
|
id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
|
|
id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
|
|
@@ -1303,7 +1317,18 @@ static int e100_phy_init(struct nic *nic)
|
|
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
|
|
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
|
|
}
|
|
}
|
|
|
|
|
|
- if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
|
|
|
|
|
|
+ if (nic->phy == phy_82552_v) {
|
|
|
|
+ u16 advert = mdio_read(netdev, nic->mii.phy_id, MII_ADVERTISE);
|
|
|
|
+
|
|
|
|
+ /* Workaround Si not advertising flow-control during autoneg */
|
|
|
|
+ advert |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
|
|
|
|
+ mdio_write(netdev, nic->mii.phy_id, MII_ADVERTISE, advert);
|
|
|
|
+
|
|
|
|
+ /* Reset for the above changes to take effect */
|
|
|
|
+ bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
|
|
|
|
+ bmcr |= BMCR_RESET;
|
|
|
|
+ mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
|
|
|
|
+ } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
|
|
(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
|
|
(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
|
|
!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
|
|
!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
|
|
/* enable/disable MDI/MDI-X auto-switching. */
|
|
/* enable/disable MDI/MDI-X auto-switching. */
|
|
@@ -2134,6 +2159,9 @@ err_clean_rx:
|
|
}
|
|
}
|
|
|
|
|
|
#define MII_LED_CONTROL 0x1B
|
|
#define MII_LED_CONTROL 0x1B
|
|
|
|
+#define E100_82552_LED_OVERRIDE 0x19
|
|
|
|
+#define E100_82552_LED_ON 0x000F /* LEDTX and LED_RX both on */
|
|
|
|
+#define E100_82552_LED_OFF 0x000A /* LEDTX and LED_RX both off */
|
|
static void e100_blink_led(unsigned long data)
|
|
static void e100_blink_led(unsigned long data)
|
|
{
|
|
{
|
|
struct nic *nic = (struct nic *)data;
|
|
struct nic *nic = (struct nic *)data;
|
|
@@ -2143,10 +2171,19 @@ static void e100_blink_led(unsigned long data)
|
|
led_on_559 = 0x05,
|
|
led_on_559 = 0x05,
|
|
led_on_557 = 0x07,
|
|
led_on_557 = 0x07,
|
|
};
|
|
};
|
|
|
|
+ u16 led_reg = MII_LED_CONTROL;
|
|
|
|
+
|
|
|
|
+ if (nic->phy == phy_82552_v) {
|
|
|
|
+ led_reg = E100_82552_LED_OVERRIDE;
|
|
|
|
|
|
- nic->leds = (nic->leds & led_on) ? led_off :
|
|
|
|
- (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559;
|
|
|
|
- mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds);
|
|
|
|
|
|
+ nic->leds = (nic->leds == E100_82552_LED_ON) ?
|
|
|
|
+ E100_82552_LED_OFF : E100_82552_LED_ON;
|
|
|
|
+ } else {
|
|
|
|
+ nic->leds = (nic->leds & led_on) ? led_off :
|
|
|
|
+ (nic->mac < mac_82559_D101M) ? led_on_557 :
|
|
|
|
+ led_on_559;
|
|
|
|
+ }
|
|
|
|
+ mdio_write(nic->netdev, nic->mii.phy_id, led_reg, nic->leds);
|
|
mod_timer(&nic->blink_timer, jiffies + HZ / 4);
|
|
mod_timer(&nic->blink_timer, jiffies + HZ / 4);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2375,13 +2412,15 @@ static void e100_diag_test(struct net_device *netdev,
|
|
static int e100_phys_id(struct net_device *netdev, u32 data)
|
|
static int e100_phys_id(struct net_device *netdev, u32 data)
|
|
{
|
|
{
|
|
struct nic *nic = netdev_priv(netdev);
|
|
struct nic *nic = netdev_priv(netdev);
|
|
|
|
+ u16 led_reg = (nic->phy == phy_82552_v) ? E100_82552_LED_OVERRIDE :
|
|
|
|
+ MII_LED_CONTROL;
|
|
|
|
|
|
if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
|
|
if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
|
|
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
|
|
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
|
|
mod_timer(&nic->blink_timer, jiffies);
|
|
mod_timer(&nic->blink_timer, jiffies);
|
|
msleep_interruptible(data * 1000);
|
|
msleep_interruptible(data * 1000);
|
|
del_timer_sync(&nic->blink_timer);
|
|
del_timer_sync(&nic->blink_timer);
|
|
- mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0);
|
|
|
|
|
|
+ mdio_write(netdev, nic->mii.phy_id, led_reg, 0);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -2686,6 +2725,9 @@ static void __devexit e100_remove(struct pci_dev *pdev)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */
|
|
|
|
+#define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */
|
|
|
|
+#define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */
|
|
static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
{
|
|
{
|
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
|
@@ -2698,6 +2740,15 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
pci_save_state(pdev);
|
|
pci_save_state(pdev);
|
|
|
|
|
|
if ((nic->flags & wol_magic) | e100_asf(nic)) {
|
|
if ((nic->flags & wol_magic) | e100_asf(nic)) {
|
|
|
|
+ /* enable reverse auto-negotiation */
|
|
|
|
+ if (nic->phy == phy_82552_v) {
|
|
|
|
+ u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
|
|
|
|
+ E100_82552_SMARTSPEED);
|
|
|
|
+
|
|
|
|
+ mdio_write(netdev, nic->mii.phy_id,
|
|
|
|
+ E100_82552_SMARTSPEED, smartspeed |
|
|
|
|
+ E100_82552_REV_ANEG | E100_82552_ANEG_NOW);
|
|
|
|
+ }
|
|
if (pci_enable_wake(pdev, PCI_D3cold, true))
|
|
if (pci_enable_wake(pdev, PCI_D3cold, true))
|
|
pci_enable_wake(pdev, PCI_D3hot, true);
|
|
pci_enable_wake(pdev, PCI_D3hot, true);
|
|
} else {
|
|
} else {
|
|
@@ -2721,6 +2772,16 @@ static int e100_resume(struct pci_dev *pdev)
|
|
/* ack any pending wake events, disable PME */
|
|
/* ack any pending wake events, disable PME */
|
|
pci_enable_wake(pdev, 0, 0);
|
|
pci_enable_wake(pdev, 0, 0);
|
|
|
|
|
|
|
|
+ /* disbale reverse auto-negotiation */
|
|
|
|
+ if (nic->phy == phy_82552_v) {
|
|
|
|
+ u16 smartspeed = mdio_read(netdev, nic->mii.phy_id,
|
|
|
|
+ E100_82552_SMARTSPEED);
|
|
|
|
+
|
|
|
|
+ mdio_write(netdev, nic->mii.phy_id,
|
|
|
|
+ E100_82552_SMARTSPEED,
|
|
|
|
+ smartspeed & ~(E100_82552_REV_ANEG));
|
|
|
|
+ }
|
|
|
|
+
|
|
netif_device_attach(netdev);
|
|
netif_device_attach(netdev);
|
|
if (netif_running(netdev))
|
|
if (netif_running(netdev))
|
|
e100_up(nic);
|
|
e100_up(nic);
|