[kernel] r14669 - in dists/lenny/linux-2.6/debian: . patches/features/all patches/series

Dann Frazier dannf at alioth.debian.org
Tue Nov 24 05:27:30 UTC 2009


Author: dannf
Date: Tue Nov 24 05:27:27 2009
New Revision: 14669

Log:
igb: Add 82576 MAC support (Closes: #522922), backport
by Ben Hutchings

Added:
   dists/lenny/linux-2.6/debian/patches/features/all/igb-add-82576-MAC-support.patch
Modified:
   dists/lenny/linux-2.6/debian/changelog
   dists/lenny/linux-2.6/debian/patches/series/21

Modified: dists/lenny/linux-2.6/debian/changelog
==============================================================================
--- dists/lenny/linux-2.6/debian/changelog	Mon Nov 23 23:26:17 2009	(r14668)
+++ dists/lenny/linux-2.6/debian/changelog	Tue Nov 24 05:27:27 2009	(r14669)
@@ -17,6 +17,8 @@
   [ dann frazier ]
   * floppy: request and release only the ports we actually use
     (Closes: #332942)
+  * igb: Add 82576 MAC support (Closes: #522922), backport
+    by Ben Hutchings
 
  -- Ben Hutchings <ben at decadent.org.uk>  Sat, 24 Oct 2009 23:45:45 +0100
 

Added: dists/lenny/linux-2.6/debian/patches/features/all/igb-add-82576-MAC-support.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/lenny/linux-2.6/debian/patches/features/all/igb-add-82576-MAC-support.patch	Tue Nov 24 05:27:27 2009	(r14669)
@@ -0,0 +1,935 @@
+From 4a8d64c6f6eed7d5761ce4bb396b46b1d654dac3 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Mon, 12 Oct 2009 01:49:31 +0100
+Subject: [PATCH] igb: add 82576 MAC support
+
+Combination of these upstream changes:
+
+commit 2d064c06fecadadcb81a452acd373af00dfb1fec
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Tue Jul 8 15:10:12 2008 -0700
+
+    igb: add 82576 MAC support
+
+commit 726c09e7b6b7b9f9015ae7ce803ba4cd67121d67
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Mon Aug 4 14:59:56 2008 -0700
+
+    igb: fixes 82576 serdes init to correctly support manual flow control changes
+
+commit 17fc7004a3f552b52274b6b2fbbebd7ff76dc1d5
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Fri Aug 8 16:51:26 2008 -0700
+
+    igb: remove 82576 quad adapter
+
+commit 921aa7491201b238589ab9f94184b18a1ed00e12
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Wed Jan 21 14:42:28 2009 -0800
+
+    igb: make certain to power on optics for 82576 fiber nics
+
+commit 9eb2341d0df6e5d33508008879987bf5bb146804
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Fri Mar 13 20:42:15 2009 +0000
+
+    igb: add support for another dual port 82576 non-security nic
+
+commit c8ea5ea9da338d6af015148105f07fc35eda8a92
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Fri Mar 13 20:42:35 2009 +0000
+
+    igb: add support for 82576 quad copper adapter
+
+commit a6a605691f666482a261d69da7e0cef7048a434b
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Tue Mar 31 20:38:38 2009 +0000
+
+    igb: increase delay for copper link setup
+
+commit 4703bf73bd5b0d43c3eb5b547398d4f62dc5d4e1
+Author: Alexander Duyck <alexander.h.duyck at intel.com>
+Date:   Thu Jul 23 18:09:48 2009 +0000
+
+    igb: add support for 82576 mezzanine card
+
+but without unnecessary changes to common code and without WoL support
+for the quad-port card.
+---
+ drivers/net/igb/e1000_82575.c   |  125 +++++++++++++++++++++++++++++++++-
+ drivers/net/igb/e1000_82575.h   |    4 +
+ drivers/net/igb/e1000_defines.h |   11 +++
+ drivers/net/igb/e1000_hw.h      |    7 ++
+ drivers/net/igb/e1000_mac.c     |   15 ++---
+ drivers/net/igb/e1000_phy.c     |    7 ++-
+ drivers/net/igb/e1000_regs.h    |    7 ++-
+ drivers/net/igb/igb_ethtool.c   |  146 +++++++++++++++++++++++++++++---------
+ drivers/net/igb/igb_main.c      |  142 +++++++++++++++++++++++++++++++-------
+ 9 files changed, 390 insertions(+), 74 deletions(-)
+
+diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
+index cda3ec8..68c5026 100644
+--- a/drivers/net/igb/e1000_82575.c
++++ b/drivers/net/igb/e1000_82575.c
+@@ -84,6 +84,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
+ 	case E1000_DEV_ID_82575GB_QUAD_COPPER:
+ 		mac->type = e1000_82575;
+ 		break;
++	case E1000_DEV_ID_82576:
++	case E1000_DEV_ID_82576_NS:
++	case E1000_DEV_ID_82576_FIBER:
++	case E1000_DEV_ID_82576_SERDES:
++	case E1000_DEV_ID_82576_QUAD_COPPER:
++	case E1000_DEV_ID_82576_SERDES_QUAD:
++		mac->type = e1000_82576;
++		break;
+ 	default:
+ 		return -E1000_ERR_MAC_INIT;
+ 		break;
+@@ -128,6 +136,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
+ 	mac->mta_reg_count = 128;
+ 	/* Set rar entry count */
+ 	mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
++	if (mac->type == e1000_82576)
++		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
+ 	/* Set if part includes ASF firmware */
+ 	mac->asf_firmware_present = true;
+ 	/* Set if manageability features are enabled. */
+@@ -774,13 +784,49 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed,
+  **/
+ static void igb_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index)
+ {
+-	if (index < E1000_RAR_ENTRIES_82575)
++	if (index < hw->mac.rar_entry_count)
+ 		igb_rar_set(hw, addr, index);
+ 
+ 	return;
+ }
+ 
+ /**
++ *  igb_shutdown_fiber_serdes_link_82575 - Remove link during power down
++ *  @hw: pointer to the HW structure
++ *
++ *  In the case of fiber serdes, shut down optics and PCS on driver unload
++ *  when management pass thru is not enabled.
++ **/
++void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
++{
++	u32 reg;
++
++	if (hw->mac.type != e1000_82576 ||
++	    (hw->phy.media_type != e1000_media_type_fiber &&
++	     hw->phy.media_type != e1000_media_type_internal_serdes))
++		return;
++
++	/* if the management interface is not enabled, then power down */
++	if (!igb_enable_mng_pass_thru(hw)) {
++		/* Disable PCS to turn off link */
++		reg = rd32(E1000_PCS_CFG0);
++		reg &= ~E1000_PCS_CFG_PCS_EN;
++		wr32(E1000_PCS_CFG0, reg);
++
++		/* shutdown the laser */
++		reg = rd32(E1000_CTRL_EXT);
++		reg |= E1000_CTRL_EXT_SDP7_DATA;
++		wr32(E1000_CTRL_EXT, reg);
++
++		/* flush the write to verify completion */
++		wrfl();
++		msleep(1);
++	}
++
++	return;
++}
++
++/**
+  *  e1000_reset_hw_82575 - Reset hardware
+  *  @hw: pointer to the HW structure
+  *
+@@ -996,6 +1042,13 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
+ 	       E1000_CTRL_SWDPIN1;
+ 	wr32(E1000_CTRL, reg);
+ 
++	/* Power on phy for 82576 fiber adapters */
++	if (hw->mac.type == e1000_82576) {
++		reg = rd32(E1000_CTRL_EXT);
++		reg &= ~E1000_CTRL_EXT_SDP7_DATA;
++		wr32(E1000_CTRL_EXT, reg);
++	}
++
+ 	/* Set switch control to serdes energy detect */
+ 	reg = rd32(E1000_CONNSW);
+ 	reg |= E1000_CONNSW_ENRGSRC;
+@@ -1028,6 +1081,12 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw)
+ 		       E1000_PCS_LCTL_FORCE_LINK;     /* Force Link */
+ 		hw_dbg(hw, "Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg);
+ 	}
++
++	if (hw->mac.type == e1000_82576) {
++		reg |= E1000_PCS_LCTL_FORCE_FCTRL;
++		igb_force_mac_fc(hw);
++	}
++
+ 	wr32(E1000_PCS_LCTL, reg);
+ 
+ 	return 0;
+@@ -1125,6 +1184,70 @@ out:
+ }
+ 
+ /**
++ *  igb_translate_register_82576 - Translate the proper register offset
++ *  @reg: e1000 register to be read
++ *
++ *  Registers in 82576 are located in different offsets than other adapters
++ *  even though they function in the same manner.  This function takes in
++ *  the name of the register to read and returns the correct offset for
++ *  82576 silicon.
++ **/
++u32 igb_translate_register_82576(u32 reg)
++{
++	/*
++	 * Some of the Kawela registers are located at different
++	 * offsets than they are in older adapters.
++	 * Despite the difference in location, the registers
++	 * function in the same manner.
++	 */
++	switch (reg) {
++	case E1000_TDBAL(0):
++		reg = 0x0E000;
++		break;
++	case E1000_TDBAH(0):
++		reg = 0x0E004;
++		break;
++	case E1000_TDLEN(0):
++		reg = 0x0E008;
++		break;
++	case E1000_TDH(0):
++		reg = 0x0E010;
++		break;
++	case E1000_TDT(0):
++		reg = 0x0E018;
++		break;
++	case E1000_TXDCTL(0):
++		reg = 0x0E028;
++		break;
++	case E1000_RDBAL(0):
++		reg = 0x0C000;
++		break;
++	case E1000_RDBAH(0):
++		reg = 0x0C004;
++		break;
++	case E1000_RDLEN(0):
++		reg = 0x0C008;
++		break;
++	case E1000_RDH(0):
++		reg = 0x0C010;
++		break;
++	case E1000_RDT(0):
++		reg = 0x0C018;
++		break;
++	case E1000_RXDCTL(0):
++		reg = 0x0C028;
++		break;
++	case E1000_SRRCTL(0):
++		reg = 0x0C00C;
++		break;
++	default:
++		break;
++	}
++
++	return reg;
++}
++
++/**
+  *  e1000_reset_init_script_82575 - Inits HW defaults after reset
+  *  @hw: pointer to the HW structure
+  *
+diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
+index 76ea846..fc2c8dd 100644
+--- a/drivers/net/igb/e1000_82575.h
++++ b/drivers/net/igb/e1000_82575.h
+@@ -28,7 +28,11 @@
+ #ifndef _E1000_82575_H_
+ #define _E1000_82575_H_
+ 
++u32 igb_translate_register_82576(u32 reg);
++extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
++
+ #define E1000_RAR_ENTRIES_82575   16
++#define E1000_RAR_ENTRIES_82576   24
+ 
+ /* SRRCTL bit definitions */
+ #define E1000_SRRCTL_BSIZEPKT_SHIFT                     10 /* Shift _right_ */
+diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
+index 8da9ffe..c1b36d9 100644
+--- a/drivers/net/igb/e1000_defines.h
++++ b/drivers/net/igb/e1000_defines.h
+@@ -90,6 +90,11 @@
+ #define E1000_I2CCMD_ERROR            0x80000000
+ #define E1000_MAX_SGMII_PHY_REG_ADDR  255
+ #define E1000_I2CCMD_PHY_TIMEOUT      200
++#define E1000_IVAR_VALID              0x80
++#define E1000_GPIE_NSICR              0x00000001
++#define E1000_GPIE_MSIX_MODE          0x00000010
++#define E1000_GPIE_EIAME              0x40000000
++#define E1000_GPIE_PBA                0x80000000
+ 
+ /* Receive Decriptor bit definitions */
+ #define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
+@@ -213,6 +218,7 @@
+ /* Device Control */
+ #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
+ #define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
++#define E1000_CTRL_LRST     0x00000008  /* Link reset. 0=normal,1=reset */
+ #define E1000_CTRL_ASDE     0x00000020  /* Auto-speed detect enable */
+ #define E1000_CTRL_SLU      0x00000040  /* Set link up (Force Link) */
+ #define E1000_CTRL_ILOS     0x00000080  /* Invert Loss-Of Signal */
+@@ -244,15 +250,18 @@
+  */
+ 
+ #define E1000_CONNSW_ENRGSRC             0x4
++#define E1000_PCS_CFG_PCS_EN             8
+ #define E1000_PCS_LCTL_FLV_LINK_UP       1
+ #define E1000_PCS_LCTL_FSV_100           2
+ #define E1000_PCS_LCTL_FSV_1000          4
+ #define E1000_PCS_LCTL_FDV_FULL          8
+ #define E1000_PCS_LCTL_FSD               0x10
+ #define E1000_PCS_LCTL_FORCE_LINK        0x20
++#define E1000_PCS_LCTL_FORCE_FCTRL       0x80
+ #define E1000_PCS_LCTL_AN_ENABLE         0x10000
+ #define E1000_PCS_LCTL_AN_RESTART        0x20000
+ #define E1000_PCS_LCTL_AN_TIMEOUT        0x40000
++#define E1000_ENABLE_SERDES_LOOPBACK     0x0410
+ 
+ #define E1000_PCS_LSTS_LINK_OK           1
+ #define E1000_PCS_LSTS_SPEED_100         2
+@@ -359,6 +368,7 @@
+ #define E1000_PBA_16K 0x0010    /* 16KB, default TX allocation */
+ #define E1000_PBA_24K 0x0018
+ #define E1000_PBA_34K 0x0022
++#define E1000_PBA_64K 0x0040    /* 64KB */
+ 
+ #define IFS_MAX       80
+ #define IFS_MIN       40
+@@ -539,6 +549,7 @@
+ /* PHY Control Register */
+ #define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
+ #define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
++#define MII_CR_POWER_DOWN       0x0800  /* Power down */
+ #define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
+ #define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
+ #define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
+diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
+index 7b2c70a..e0d2f70 100644
+--- a/drivers/net/igb/e1000_hw.h
++++ b/drivers/net/igb/e1000_hw.h
+@@ -38,6 +38,12 @@
+ 
+ struct e1000_hw;
+ 
++#define E1000_DEV_ID_82576                    0x10C9
++#define E1000_DEV_ID_82576_FIBER              0x10E6
++#define E1000_DEV_ID_82576_SERDES             0x10E7
++#define E1000_DEV_ID_82576_QUAD_COPPER        0x10E8
++#define E1000_DEV_ID_82576_NS                 0x150A
++#define E1000_DEV_ID_82576_SERDES_QUAD        0x150D
+ #define E1000_DEV_ID_82575EB_COPPER           0x10A7
+ #define E1000_DEV_ID_82575EB_FIBER_SERDES     0x10A9
+ #define E1000_DEV_ID_82575GB_QUAD_COPPER      0x10D6
+@@ -50,6 +56,7 @@ struct e1000_hw;
+ enum e1000_mac_type {
+ 	e1000_undefined = 0,
+ 	e1000_82575,
++	e1000_82576,
+ 	e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
+ };
+ 
+diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
+index 3e84a3f..c4e254b 100644
+--- a/drivers/net/igb/e1000_mac.c
++++ b/drivers/net/igb/e1000_mac.c
+@@ -156,6 +156,7 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
+ void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
+ {
+ 	u32 i;
++	u8 addr[6] = {0,0,0,0,0,0};
+ 
+ 	/* Setup the receive address */
+ 	hw_dbg(hw, "Programming MAC Address into RAR[0]\n");
+@@ -164,12 +165,8 @@ void igb_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
+ 
+ 	/* Zero out the other (rar_entry_count - 1) receive addresses */
+ 	hw_dbg(hw, "Clearing RAR[1-%u]\n", rar_count-1);
+-	for (i = 1; i < rar_count; i++) {
+-		array_wr32(E1000_RA, (i << 1), 0);
+-		wrfl();
+-		array_wr32(E1000_RA, ((i << 1) + 1), 0);
+-		wrfl();
+-	}
++	for (i = 1; i < rar_count; i++)
++		hw->mac.ops.rar_set(hw, addr, i);
+ }
+ 
+ /**
+@@ -316,6 +313,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,
+ {
+ 	u32 hash_value;
+ 	u32 i;
++	u8 addr[6] = {0,0,0,0,0,0};
+ 
+ 	/*
+ 	 * Load the first set of multicast addresses into the exact
+@@ -328,10 +326,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,
+ 			mc_addr_count--;
+ 			mc_addr_list += ETH_ALEN;
+ 		} else {
+-			array_wr32(E1000_RA, i << 1, 0);
+-			wrfl();
+-			array_wr32(E1000_RA, (i << 1) + 1, 0);
+-			wrfl();
++			hw->mac.ops.rar_set(hw, addr, i);
+ 		}
+ 	}
+ 
+diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
+index 08a86b1..1f4654c 100644
+--- a/drivers/net/igb/e1000_phy.c
++++ b/drivers/net/igb/e1000_phy.c
+@@ -455,8 +455,11 @@ s32 igb_copper_link_setup_igp(struct e1000_hw *hw)
+ 		goto out;
+ 	}
+ 
+-	/* Wait 15ms for MAC to configure PHY from NVM settings. */
+-	msleep(15);
++	/*
++	 * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
++	 * timeout issues when LFS is enabled.
++	 */
++	msleep(100);
+ 
+ 	/*
+ 	 * The NVM settings will configure LPLU in D3 for
+diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
+index ff187b7..d8ef50c 100644
+--- a/drivers/net/igb/e1000_regs.h
++++ b/drivers/net/igb/e1000_regs.h
+@@ -56,6 +56,9 @@
+ #define E1000_EIMC     0x01528  /* Ext. Interrupt Mask Clear - WO */
+ #define E1000_EIAC     0x0152C  /* Ext. Interrupt Auto Clear - RW */
+ #define E1000_EIAM     0x01530  /* Ext. Interrupt Ack Auto Clear Mask - RW */
++#define E1000_GPIE     0x01514  /* General Purpose Interrupt Enable - RW */
++#define E1000_IVAR0    0x01700  /* Interrupt Vector Allocation (array) - RW */
++#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
+ #define E1000_TCTL     0x00400  /* TX Control - RW */
+ #define E1000_TCTL_EXT 0x00404  /* Extended TX Control - RW */
+ #define E1000_TIPG     0x00410  /* TX Inter-packet gap -RW */
+@@ -217,6 +220,7 @@
+ #define E1000_RFCTL    0x05008  /* Receive Filter Control*/
+ #define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
+ #define E1000_RA       0x05400  /* Receive Address - RW Array */
++#define E1000_RA2      0x054E0  /* 2nd half of receive address array - RW Array */
+ #define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
+ #define E1000_VMD_CTL  0x0581C  /* VMDq Control - RW */
+ #define E1000_WUC      0x05800  /* Wakeup Control - RW */
+@@ -256,7 +260,8 @@
+ #define E1000_RETA(_i)  (0x05C00 + ((_i) * 4))
+ #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW Array */
+ 
+-#define E1000_REGISTER(a, reg) reg
++#define E1000_REGISTER(a, reg) (((a)->mac.type < e1000_82576) \
++                               ? reg : igb_translate_register_82576(reg))
+ 
+ #define wr32(reg, value) (writel(value, hw->hw_addr + reg))
+ #define rd32(reg) (readl(hw->hw_addr + reg))
+diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
+index 0447f9b..8bcbb0f 100644
+--- a/drivers/net/igb/igb_ethtool.c
++++ b/drivers/net/igb/igb_ethtool.c
+@@ -829,8 +829,9 @@ err_setup:
+ /* ethtool register test data */
+ struct igb_reg_test {
+ 	u16 reg;
+-	u8  array_len;
+-	u8  test_type;
++	u16 reg_offset;
++	u16 array_len;
++	u16 test_type;
+ 	u32 mask;
+ 	u32 write;
+ };
+@@ -852,34 +853,72 @@ struct igb_reg_test {
+ #define TABLE64_TEST_LO	5
+ #define TABLE64_TEST_HI	6
+ 
+-/* default register test */
++/* 82576 reg test */
++static struct igb_reg_test reg_test_82576[] = {
++	{ E1000_FCAL,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_FCAH,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
++	{ E1000_FCT,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
++	{ E1000_VET,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RDBAL(0),  0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
++	{ E1000_RDBAH(0),  0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RDLEN(0),  0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
++	{ E1000_RDBAL(4),  0x40,  8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
++	{ E1000_RDBAH(4),  0x40,  8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RDLEN(4),  0x40,  8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
++	/* Enable all four RX queues before testing. */
++	{ E1000_RXDCTL(0), 0x100, 1,  WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE },
++	/* RDH is read-only for 82576, only test RDT. */
++	{ E1000_RDT(0),	   0x100, 4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
++	{ E1000_RXDCTL(0), 0x100, 4,  WRITE_NO_TEST, 0, 0 },
++	{ E1000_FCRTH,	   0x100, 1,  PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
++	{ E1000_FCTTV,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
++	{ E1000_TIPG,	   0x100, 1,  PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
++	{ E1000_TDBAL(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
++	{ E1000_TDBAH(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_TDLEN(0),  0x100, 4,  PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
++	{ E1000_TDBAL(4),  0x40, 8,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
++	{ E1000_TDBAH(4),  0x40, 8,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_TDLEN(4),  0x40, 8,  PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
++	{ E1000_RCTL,	   0x100, 1,  SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
++	{ E1000_RCTL, 	   0x100, 1,  SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
++	{ E1000_RCTL, 	   0x100, 1,  SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
++	{ E1000_TCTL,	   0x100, 1,  SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
++	{ E1000_RA,	   0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RA,	   0, 16, TABLE64_TEST_HI, 0x83FFFFFF, 0xFFFFFFFF },
++	{ E1000_RA2,	   0, 8, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RA2,	   0, 8, TABLE64_TEST_HI, 0x83FFFFFF, 0xFFFFFFFF },
++	{ E1000_MTA,	   0, 128,TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ 0, 0, 0, 0 }
++};
++
++/* 82575 register test */
+ static struct igb_reg_test reg_test_82575[] = {
+-	{ E1000_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+-	{ E1000_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+-	{ E1000_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+-	{ E1000_VET, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+-	{ E1000_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+-	{ E1000_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+-	{ E1000_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
++	{ E1000_FCAL,      0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_FCAH,      0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
++	{ E1000_FCT,       0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
++	{ E1000_VET,       0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RDBAL(0),  0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
++	{ E1000_RDBAH(0),  0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RDLEN(0),  0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+ 	/* Enable all four RX queues before testing. */
+-	{ E1000_RXDCTL(0), 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE },
++	{ E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE },
+ 	/* RDH is read-only for 82575, only test RDT. */
+-	{ E1000_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+-	{ E1000_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 },
+-	{ E1000_FCRTH, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
+-	{ E1000_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+-	{ E1000_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
+-	{ E1000_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+-	{ E1000_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+-	{ E1000_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+-	{ E1000_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+-	{ E1000_RCTL, 1, SET_READ_TEST, 0x04CFB3FE, 0x003FFFFB },
+-	{ E1000_RCTL, 1, SET_READ_TEST, 0x04CFB3FE, 0xFFFFFFFF },
+-	{ E1000_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+-	{ E1000_TXCW, 1, PATTERN_TEST, 0xC000FFFF, 0x0000FFFF },
+-	{ E1000_RA, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF },
+-	{ E1000_RA, 16, TABLE64_TEST_HI, 0x800FFFFF, 0xFFFFFFFF },
+-	{ E1000_MTA, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RDT(0),    0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
++	{ E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 },
++	{ E1000_FCRTH,     0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
++	{ E1000_FCTTV,     0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
++	{ E1000_TIPG,      0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
++	{ E1000_TDBAL(0),  0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
++	{ E1000_TDBAH(0),  0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_TDLEN(0),  0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
++	{ E1000_RCTL,      0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
++	{ E1000_RCTL,      0x100, 1, SET_READ_TEST, 0x04CFB3FE, 0x003FFFFB },
++	{ E1000_RCTL,      0x100, 1, SET_READ_TEST, 0x04CFB3FE, 0xFFFFFFFF },
++	{ E1000_TCTL,      0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
++	{ E1000_TXCW,      0x100, 1, PATTERN_TEST, 0xC000FFFF, 0x0000FFFF },
++	{ E1000_RA,        0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF },
++	{ E1000_RA,        0, 16, TABLE64_TEST_HI, 0x800FFFFF, 0xFFFFFFFF },
++	{ E1000_MTA,       0, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ 	{ 0, 0, 0, 0 }
+ };
+ 
+@@ -939,7 +978,15 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)
+ 	u32 i, toggle;
+ 
+ 	toggle = 0x7FFFF3FF;
+-	test = reg_test_82575;
++
++	switch (adapter->hw.mac.type) {
++	case e1000_82576:
++		test = reg_test_82576;
++		break;
++	default:
++		test = reg_test_82575;
++		break;
++	}
+ 
+ 	/* Because the status register is such a special case,
+ 	 * we handle it separately from the rest of the register
+@@ -966,19 +1013,19 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)
+ 		for (i = 0; i < test->array_len; i++) {
+ 			switch (test->test_type) {
+ 			case PATTERN_TEST:
+-				REG_PATTERN_TEST(test->reg + (i * 0x100),
++				REG_PATTERN_TEST(test->reg + (i * test->reg_offset),
+ 						test->mask,
+ 						test->write);
+ 				break;
+ 			case SET_READ_TEST:
+-				REG_SET_AND_CHECK(test->reg + (i * 0x100),
++				REG_SET_AND_CHECK(test->reg + (i * test->reg_offset),
+ 						test->mask,
+ 						test->write);
+ 				break;
+ 			case WRITE_NO_TEST:
+ 				writel(test->write,
+ 				    (adapter->hw.hw_addr + test->reg)
+-					+ (i * 0x100));
++					+ (i * test->reg_offset));
+ 				break;
+ 			case TABLE32_TEST:
+ 				REG_PATTERN_TEST(test->reg + (i * 4),
+@@ -1394,13 +1441,39 @@ static int igb_set_phy_loopback(struct igb_adapter *adapter)
+ static int igb_setup_loopback_test(struct igb_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+-	u32 rctl;
++	u32 reg;
+ 
+ 	if (hw->phy.media_type == e1000_media_type_fiber ||
+ 	    hw->phy.media_type == e1000_media_type_internal_serdes) {
+-		rctl = rd32(E1000_RCTL);
+-		rctl |= E1000_RCTL_LBM_TCVR;
+-		wr32(E1000_RCTL, rctl);
++		reg = rd32(E1000_RCTL);
++		reg |= E1000_RCTL_LBM_TCVR;
++		wr32(E1000_RCTL, reg);
++
++		wr32(E1000_SCTL, E1000_ENABLE_SERDES_LOOPBACK);
++
++		reg = rd32(E1000_CTRL);
++		reg &= ~(E1000_CTRL_RFCE |
++			 E1000_CTRL_TFCE |
++			 E1000_CTRL_LRST);
++		reg |= E1000_CTRL_SLU |
++		       E1000_CTRL_FD;
++		wr32(E1000_CTRL, reg);
++
++		/* Unset switch control to serdes energy detect */
++		reg = rd32(E1000_CONNSW);
++		reg &= ~E1000_CONNSW_ENRGSRC;
++		wr32(E1000_CONNSW, reg);
++
++		/* Set PCS register for forced speed */
++		reg = rd32(E1000_PCS_LCTL);
++		reg &= ~E1000_PCS_LCTL_AN_ENABLE;     /* Disable Autoneg*/
++		reg |= E1000_PCS_LCTL_FLV_LINK_UP |   /* Force link up */
++		       E1000_PCS_LCTL_FSV_1000 |      /* Force 1000    */
++		       E1000_PCS_LCTL_FDV_FULL |      /* SerDes Full duplex */
++		       E1000_PCS_LCTL_FSD |           /* Force Speed */
++		       E1000_PCS_LCTL_FORCE_LINK;     /* Force Link */
++		wr32(E1000_PCS_LCTL, reg);
++
+ 		return 0;
+ 	} else if (hw->phy.media_type == e1000_media_type_copper) {
+ 		return igb_set_phy_loopback(adapter);
+@@ -1656,10 +1729,13 @@ static int igb_wol_exclusion(struct igb_adapter *adapter,
+ 
+ 	switch (hw->device_id) {
+ 	case E1000_DEV_ID_82575GB_QUAD_COPPER:
++	case E1000_DEV_ID_82576_QUAD_COPPER:
+ 		/* WoL not supported */
+ 		wol->supported = 0;
+ 		break;
+ 	case E1000_DEV_ID_82575EB_FIBER_SERDES:
++	case E1000_DEV_ID_82576_FIBER:
++	case E1000_DEV_ID_82576_SERDES:
+ 		/* Wake events not supported on port B */
+ 		if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) {
+ 			wol->supported = 0;
+diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
+index e79a26a..37a6fca 100644
+--- a/drivers/net/igb/igb_main.c
++++ b/drivers/net/igb/igb_main.c
+@@ -49,7 +49,7 @@ char igb_driver_name[] = "igb";
+ char igb_driver_version[] = DRV_VERSION;
+ static const char igb_driver_string[] =
+ 				"Intel(R) Gigabit Ethernet Network Driver";
+-static const char igb_copyright[] = "Copyright (c) 2007 Intel Corporation.";
++static const char igb_copyright[] = "Copyright (c) 2008 Intel Corporation.";
+ 
+ 
+ static const struct e1000_info *igb_info_tbl[] = {
+@@ -57,6 +57,12 @@ static const struct e1000_info *igb_info_tbl[] = {
+ };
+ 
+ static struct pci_device_id igb_pci_tbl[] = {
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 },
+@@ -245,6 +251,10 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
+ {
+ 	u32 msixbm = 0;
+ 	struct e1000_hw *hw = &adapter->hw;
++	u32 ivar, index;
++
++	switch (hw->mac.type) {
++	case e1000_82575:
+ 		/* The 82575 assigns vectors using a bitmask, which matches the
+ 		   bitmask for the EICR/EIMS/EIMC registers.  To assign one
+ 		   or more queues to a vector, we write the appropriate bits
+@@ -259,6 +269,47 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
+ 				  E1000_EICR_TX_QUEUE0 << tx_queue;
+ 		}
+ 		array_wr32(E1000_MSIXBM(0), msix_vector, msixbm);
++		break;
++	case e1000_82576:
++		/* Kawela uses a table-based method for assigning vectors.
++		   Each queue has a single entry in the table to which we write
++		   a vector number along with a "valid" bit.  Sadly, the layout
++		   of the table is somewhat counterintuitive. */
++		if (rx_queue > IGB_N0_QUEUE) {
++			index = (rx_queue & 0x7);
++			ivar = array_rd32(E1000_IVAR0, index);
++			if (rx_queue < 8) {
++				/* vector goes into low byte of register */
++				ivar = ivar & 0xFFFFFF00;
++				ivar |= msix_vector | E1000_IVAR_VALID;
++			} else {
++				/* vector goes into third byte of register */
++				ivar = ivar & 0xFF00FFFF;
++				ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
++			}
++			adapter->rx_ring[rx_queue].eims_value= 1 << msix_vector;
++			array_wr32(E1000_IVAR0, index, ivar);
++		}
++		if (tx_queue > IGB_N0_QUEUE) {
++			index = (tx_queue & 0x7);
++			ivar = array_rd32(E1000_IVAR0, index);
++			if (tx_queue < 8) {
++				/* vector goes into second byte of register */
++				ivar = ivar & 0xFFFF00FF;
++				ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
++			} else {
++				/* vector goes into high byte of register */
++				ivar = ivar & 0x00FFFFFF;
++				ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
++			}
++			adapter->tx_ring[tx_queue].eims_value= 1 << msix_vector;
++			array_wr32(E1000_IVAR0, index, ivar);
++		}
++		break;
++	default:
++		BUG();
++		break;
++	}
+ }
+ 
+ /**
+@@ -274,6 +325,12 @@ static void igb_configure_msix(struct igb_adapter *adapter)
+ 	struct e1000_hw *hw = &adapter->hw;
+ 
+ 	adapter->eims_enable_mask = 0;
++	if (hw->mac.type == e1000_82576)
++		/* Turn on MSI-X capability first, or our settings
++		 * won't stick.  And it will take days to debug. */
++		wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
++				   E1000_GPIE_PBA | E1000_GPIE_EIAME |
++				   E1000_GPIE_NSICR);
+ 
+ 	for (i = 0; i < adapter->num_tx_queues; i++) {
+ 		struct igb_ring *tx_ring = &adapter->tx_ring[i];
+@@ -299,6 +356,8 @@ static void igb_configure_msix(struct igb_adapter *adapter)
+ 
+ 
+ 	/* set vector for other causes, i.e. link changes */
++	switch (hw->mac.type) {
++	case e1000_82575:
+ 		array_wr32(E1000_MSIXBM(0), vector++,
+ 				      E1000_EIMS_OTHER);
+ 
+@@ -315,7 +374,18 @@ static void igb_configure_msix(struct igb_adapter *adapter)
+ 
+ 		wr32(E1000_CTRL_EXT, tmp);
+ 		adapter->eims_enable_mask |= E1000_EIMS_OTHER;
++		break;
++
++	case e1000_82576:
++		tmp = (vector++ | E1000_IVAR_VALID) << 8;
++		wr32(E1000_IVAR_MISC, tmp);
+ 
++		adapter->eims_enable_mask = (1 << (vector)) - 1;
++		break;
++	default:
++		/* do nothing, since nothing else supports MSI-X */
++		break;
++	} /* switch (hw->mac.type) */
+ 	wrfl();
+ }
+ 
+@@ -450,7 +520,20 @@ static int igb_request_irq(struct igb_adapter *adapter)
+ 		igb_free_all_rx_resources(adapter);
+ 		adapter->num_rx_queues = 1;
+ 		igb_alloc_queues(adapter);
++	} else {
++		switch (hw->mac.type) {
++		case e1000_82575:
++			wr32(E1000_MSIXBM(0),
++			     (E1000_EICR_RX_QUEUE0 | E1000_EIMS_OTHER));
++			break;
++		case e1000_82576:
++			wr32(E1000_IVAR0, E1000_IVAR_VALID);
++			break;
++		default:
++			break;
++		}
+ 	}
++
+ 	if (adapter->msi_enabled) {
+ 		err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0,
+ 				  netdev->name, netdev);
+@@ -737,16 +820,23 @@ void igb_reinit_locked(struct igb_adapter *adapter)
+ void igb_reset(struct igb_adapter *adapter)
+ {
+ 	struct e1000_hw *hw = &adapter->hw;
+-	struct e1000_fc_info *fc = &adapter->hw.fc;
++	struct e1000_mac_info *mac = &hw->mac;
++	struct e1000_fc_info *fc = &hw->fc;
+ 	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
+ 	u16 hwm;
+ 
+ 	/* Repartition Pba for greater than 9k mtu
+ 	 * To take effect CTRL.RST is required.
+ 	 */
+-	pba = E1000_PBA_34K;
++	if (mac->type != e1000_82576) {
++		pba = E1000_PBA_34K;
++	}
++	else {
++		pba = E1000_PBA_64K;
++	}
+ 
+-	if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
++	if ((adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) &&
++	    (mac->type < e1000_82576)) {
+ 		/* adjust PBA for jumbo frames */
+ 		wr32(E1000_PBA, pba);
+ 
+@@ -785,8 +875,8 @@ void igb_reset(struct igb_adapter *adapter)
+ 			if (pba < min_rx_space)
+ 				pba = min_rx_space;
+ 		}
++		wr32(E1000_PBA, pba);
+ 	}
+-	wr32(E1000_PBA, pba);
+ 
+ 	/* flow control settings */
+ 	/* The high water mark must be low enough to fit one full frame
+@@ -795,10 +885,15 @@ void igb_reset(struct igb_adapter *adapter)
+ 	 * - 90% of the Rx FIFO size, or
+ 	 * - the full Rx FIFO size minus one full frame */
+ 	hwm = min(((pba << 10) * 9 / 10),
+-		  ((pba << 10) - adapter->max_frame_size));
++			((pba << 10) - 2 * adapter->max_frame_size));
+ 
+-	fc->high_water = hwm & 0xFFF8;	/* 8-byte granularity */
+-	fc->low_water = fc->high_water - 8;
++	if (mac->type < e1000_82576) {
++		fc->high_water = hwm & 0xFFF8;	/* 8-byte granularity */
++		fc->low_water = fc->high_water - 8;
++	} else {
++		fc->high_water = hwm & 0xFFF0;	/* 16-byte granularity */
++		fc->low_water = fc->high_water - 16;
++	}
+ 	fc->pause_time = 0xFFFF;
+ 	fc->send_xon = 1;
+ 	fc->type = fc->original_type;
+@@ -1050,9 +1145,12 @@ static int __devinit igb_probe(struct pci_dev *pdev,
+ 	 * lan on a particular port */
+ 	switch (pdev->device) {
+ 	case E1000_DEV_ID_82575GB_QUAD_COPPER:
++	case E1000_DEV_ID_82576_QUAD_COPPER:
+ 		adapter->eeprom_wol = 0;
+ 		break;
+ 	case E1000_DEV_ID_82575EB_FIBER_SERDES:
++	case E1000_DEV_ID_82576_FIBER:
++	case E1000_DEV_ID_82576_SERDES:
+ 		/* Wake events only supported on port A for dual fiber
+ 		 * regardless of eeprom setting */
+ 		if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1)
+@@ -1699,7 +1797,10 @@ static void igb_configure_rx(struct igb_adapter *adapter)
+ 
+ 		get_random_bytes(&random[0], 40);
+ 
+-		shift = 6;
++		if (hw->mac.type >= e1000_82576)
++			shift = 0;
++		else
++			shift = 6;
+ 		for (j = 0; j < (32 * 4); j++) {
+ 			reta.bytes[j & 3] =
+ 				(j % adapter->num_rx_queues) << shift;
+@@ -3878,7 +3979,7 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state)
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct igb_adapter *adapter = netdev_priv(netdev);
+ 	struct e1000_hw *hw = &adapter->hw;
+-	u32 ctrl, ctrl_ext, rctl, status;
++	u32 ctrl, rctl, status;
+ 	u32 wufc = adapter->wol;
+ #ifdef CONFIG_PM
+ 	int retval = 0;
+@@ -3921,33 +4022,24 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state)
+ 		ctrl |= E1000_CTRL_ADVD3WUC;
+ 		wr32(E1000_CTRL, ctrl);
+ 
+-		if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
+-		   adapter->hw.phy.media_type ==
+-					e1000_media_type_internal_serdes) {
+-			/* keep the laser running in D3 */
+-			ctrl_ext = rd32(E1000_CTRL_EXT);
+-			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
+-			wr32(E1000_CTRL_EXT, ctrl_ext);
+-		}
+-
+ 		/* Allow time for pending master requests to run */
+ 		igb_disable_pcie_master(&adapter->hw);
+ 
+ 		wr32(E1000_WUC, E1000_WUC_PME_EN);
+ 		wr32(E1000_WUFC, wufc);
+-		pci_enable_wake(pdev, PCI_D3hot, 1);
+-		pci_enable_wake(pdev, PCI_D3cold, 1);
+ 	} else {
+ 		wr32(E1000_WUC, 0);
+ 		wr32(E1000_WUFC, 0);
+-		pci_enable_wake(pdev, PCI_D3hot, 0);
+-		pci_enable_wake(pdev, PCI_D3cold, 0);
+ 	}
+ 
+-	/* make sure adapter isn't asleep if manageability is enabled */
+-	if (adapter->en_mng_pt) {
++	/* make sure adapter isn't asleep if manageability/wol is enabled */
++	if (wufc || adapter->en_mng_pt) {
+ 		pci_enable_wake(pdev, PCI_D3hot, 1);
+ 		pci_enable_wake(pdev, PCI_D3cold, 1);
++	} else {
++		igb_shutdown_fiber_serdes_link_82575(hw);
++		pci_enable_wake(pdev, PCI_D3hot, 0);
++		pci_enable_wake(pdev, PCI_D3cold, 0);
+ 	}
+ 
+ 	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
+-- 
+1.6.4.3
+

Modified: dists/lenny/linux-2.6/debian/patches/series/21
==============================================================================
--- dists/lenny/linux-2.6/debian/patches/series/21	Mon Nov 23 23:26:17 2009	(r14668)
+++ dists/lenny/linux-2.6/debian/patches/series/21	Tue Nov 24 05:27:27 2009	(r14669)
@@ -27,3 +27,4 @@
 - bugfix/all/sanitise-linux-socket-h.patch
 + bugfix/all/usbnet-link-down-initially-for-drivers-that-update.patch
 + bugfix/all/floppy-request-and-release-only-the-ports-we-actually-use.patch
++ features/all/igb-add-82576-MAC-support.patch



More information about the Kernel-svn-changes mailing list