diff mbox

[net-next] e100: add support for 82552 10/100 adapter

Message ID 20090319104236.11320.25733.stgit@lost.foo-projects.org
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Kirsher, Jeffrey T March 19, 2009, 10:42 a.m. UTC
From: Bruce Allan <bruce.w.allan@intel.com>

This patch enables support for the new Intel 82552 adapter (new PHY paired
with the existing MAC in the ICH7 chipset).  No new features are added to
the driver, however there are minor changes due to updated registers and a
few workarounds for hardware errata.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
---

 drivers/net/e100.c |   93 +++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 77 insertions(+), 16 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Kirsher, Jeffrey T March 19, 2009, 11:07 a.m. UTC | #1
On Thu, Mar 19, 2009 at 3:42 AM, Jeff Kirsher
<jeffrey.t.kirsher@intel.com> wrote:
> From: Bruce Allan <bruce.w.allan@intel.com>
>
> This patch enables support for the new Intel 82552 adapter (new PHY paired
> with the existing MAC in the ICH7 chipset).  No new features are added to
> the driver, however there are minor changes due to updated registers and a
> few workarounds for hardware errata.
>
> Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>

Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Sorry I left that off on the submission.
David Miller March 21, 2009, 8:25 p.m. UTC | #2
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 19 Mar 2009 04:07:14 -0700

> On Thu, Mar 19, 2009 at 3:42 AM, Jeff Kirsher
> <jeffrey.t.kirsher@intel.com> wrote:
> > From: Bruce Allan <bruce.w.allan@intel.com>
> >
> > This patch enables support for the new Intel 82552 adapter (new PHY paired
> > with the existing MAC in the ICH7 chipset).  No new features are added to
> > the driver, however there are minor changes due to updated registers and a
> > few workarounds for hardware errata.
> >
> > Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
> 
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 861d2ee..0504db9 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -167,7 +167,7 @@ 
 
 #define DRV_NAME		"e100"
 #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_COPYRIGHT		"Copyright(c) 1999-2006 Intel Corporation"
 #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(0x1094, 7),
 	INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
+	INTEL_8255X_ETHERNET_DEVICE(0x10fe, 7),
 	INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
 	INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
 	INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
@@ -275,6 +276,7 @@  enum phy {
 	phy_82562_em = 0x032002A8,
 	phy_82562_ek = 0x031002A8,
 	phy_82562_eh = 0x017002A8,
+	phy_82552_v  = 0xd061004d,
 	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)
 {
+	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);
 }
 
@@ -1276,16 +1294,12 @@  static int e100_phy_init(struct nic *nic)
 	if (addr == 32)
 		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 */
 	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);
 	}
 
-	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) &&
 		!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
 		/* enable/disable MDI/MDI-X auto-switching. */
@@ -2134,6 +2159,9 @@  err_clean_rx:
 }
 
 #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)
 {
 	struct nic *nic = (struct nic *)data;
@@ -2143,10 +2171,19 @@  static void e100_blink_led(unsigned long data)
 		led_on_559 = 0x05,
 		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);
 }
 
@@ -2375,13 +2412,15 @@  static void e100_diag_test(struct net_device *netdev,
 static int e100_phys_id(struct net_device *netdev, u32 data)
 {
 	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))
 		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
 	mod_timer(&nic->blink_timer, jiffies);
 	msleep_interruptible(data * 1000);
 	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;
 }
@@ -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)
 {
 	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);
 
 	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))
 			pci_enable_wake(pdev, PCI_D3hot, true);
 	} else {
@@ -2721,6 +2772,16 @@  static int e100_resume(struct pci_dev *pdev)
 	/* ack any pending wake events, disable PME */
 	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);
 	if (netif_running(netdev))
 		e100_up(nic);