[kernel] r22681 - in dists/jessie/linux/debian: . patches patches/features/all/e1000e

Ben Hutchings benh at moszumanska.debian.org
Sat May 23 17:15:21 UTC 2015


Author: benh
Date: Sat May 23 17:15:21 2015
New Revision: 22681

Log:
[x86] e1000e: Add support for Sunrise Point (i219) (Closes: #784546)

Added:
   dists/jessie/linux/debian/patches/features/all/e1000e/
   dists/jessie/linux/debian/patches/features/all/e1000e/0001-e1000e-initial-support-for-i219.patch
   dists/jessie/linux/debian/patches/features/all/e1000e/0002-e1000e-fix-obscure-comments.patch
   dists/jessie/linux/debian/patches/features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch
   dists/jessie/linux/debian/patches/features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch
Modified:
   dists/jessie/linux/debian/changelog
   dists/jessie/linux/debian/patches/series

Modified: dists/jessie/linux/debian/changelog
==============================================================================
--- dists/jessie/linux/debian/changelog	Sat May 23 17:12:46 2015	(r22680)
+++ dists/jessie/linux/debian/changelog	Sat May 23 17:15:21 2015	(r22681)
@@ -172,6 +172,7 @@
   * md/raid0: fix restore to sector variable in raid0_make_request
     (regression in 3.16.7-ckt11)
   * cdc_ncm: Fix tx_bytes statistics (regression in 3.16.7-ckt11)
+  * [x86] e1000e: Add support for Sunrise Point (i219) (Closes: #784546)
 
   [ Ian Campbell ]
   * [armhf] Enable support for Freescale SNVS RTC. (Closes: #782364)

Added: dists/jessie/linux/debian/patches/features/all/e1000e/0001-e1000e-initial-support-for-i219.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/jessie/linux/debian/patches/features/all/e1000e/0001-e1000e-initial-support-for-i219.patch	Sat May 23 17:15:21 2015	(r22681)
@@ -0,0 +1,1363 @@
+From: David Ertman <david.m.ertman at intel.com>
+Date: Tue, 10 Feb 2015 09:10:43 +0000
+Subject: e1000e: initial support for i219
+Origin: https://git.kernel.org/linus/79849ebc0e06d775f53d160bb1a63b000fa0947b
+Bug-Debian: https://bugs.debian.org/784546
+
+i219 is the next-generation LOM that will be available on systems with the
+Sunrise Point Platform Controller Hub (PCH) chipset from Intel.  This patch
+provides the initial support for the device.
+
+Signed-off-by: Dave Ertman <david.m.ertman at intel.com>
+Tested-by: Aaron Brown <aaron.f.brown at intel.com>
+Tested-by: Carmen Edwards <carmenx.edwards at intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
+---
+ drivers/net/ethernet/intel/e1000e/defines.h |   1 +
+ drivers/net/ethernet/intel/e1000e/e1000.h   |   2 +
+ drivers/net/ethernet/intel/e1000e/ethtool.c |   6 +-
+ drivers/net/ethernet/intel/e1000e/hw.h      |   6 +
+ drivers/net/ethernet/intel/e1000e/ich8lan.c | 770 +++++++++++++++++++++++++---
+ drivers/net/ethernet/intel/e1000e/ich8lan.h |   9 +
+ drivers/net/ethernet/intel/e1000e/netdev.c  |  50 +-
+ drivers/net/ethernet/intel/e1000e/ptp.c     |   4 +-
+ drivers/net/ethernet/intel/e1000e/regs.h    |   3 +
+ 9 files changed, 768 insertions(+), 83 deletions(-)
+
+--- a/drivers/net/ethernet/intel/e1000e/defines.h
++++ b/drivers/net/ethernet/intel/e1000e/defines.h
+@@ -141,6 +141,7 @@
+ #define E1000_RCTL_LBM_TCVR       0x000000C0    /* tcvr loopback mode */
+ #define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
+ #define E1000_RCTL_RDMTS_HALF     0x00000000    /* Rx desc min threshold size */
++#define E1000_RCTL_RDMTS_HEX      0x00010000
+ #define E1000_RCTL_MO_SHIFT       12            /* multicast offset shift */
+ #define E1000_RCTL_MO_3           0x00003000    /* multicast offset 15:4 */
+ #define E1000_RCTL_BAM            0x00008000    /* broadcast enable */
+--- a/drivers/net/ethernet/intel/e1000e/e1000.h
++++ b/drivers/net/ethernet/intel/e1000e/e1000.h
+@@ -132,6 +132,7 @@ enum e1000_boards {
+ 	board_pchlan,
+ 	board_pch2lan,
+ 	board_pch_lpt,
++	board_pch_spt
+ };
+ 
+ struct e1000_ps_page {
+@@ -501,6 +502,7 @@ extern const struct e1000_info e1000_ich
+ extern const struct e1000_info e1000_pch_info;
+ extern const struct e1000_info e1000_pch2_info;
+ extern const struct e1000_info e1000_pch_lpt_info;
++extern const struct e1000_info e1000_pch_spt_info;
+ extern const struct e1000_info e1000_es2_info;
+ 
+ void e1000e_ptp_init(struct e1000_adapter *adapter);
+--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
++++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
+@@ -896,18 +896,20 @@ static int e1000_reg_test(struct e1000_a
+ 	case e1000_pchlan:
+ 	case e1000_pch2lan:
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 		mask |= (1 << 18);
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 
+-	if (mac->type == e1000_pch_lpt)
++	if ((mac->type == e1000_pch_lpt) || (mac->type == e1000_pch_spt))
+ 		wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >>
+ 		    E1000_FWSM_WLOCK_MAC_SHIFT;
+ 
+ 	for (i = 0; i < mac->rar_entry_count; i++) {
+-		if (mac->type == e1000_pch_lpt) {
++		if ((mac->type == e1000_pch_lpt) ||
++		    (mac->type == e1000_pch_spt)) {
+ 			/* Cannot test write-protected SHRAL[n] registers */
+ 			if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac)))
+ 				continue;
+--- a/drivers/net/ethernet/intel/e1000e/hw.h
++++ b/drivers/net/ethernet/intel/e1000e/hw.h
+@@ -87,6 +87,10 @@ struct e1000_hw;
+ #define E1000_DEV_ID_PCH_I218_V2		0x15A1
+ #define E1000_DEV_ID_PCH_I218_LM3		0x15A2	/* Wildcat Point PCH */
+ #define E1000_DEV_ID_PCH_I218_V3		0x15A3	/* Wildcat Point PCH */
++#define E1000_DEV_ID_PCH_SPT_I219_LM		0x156F	/* SPT PCH */
++#define E1000_DEV_ID_PCH_SPT_I219_V		0x1570	/* SPT PCH */
++#define E1000_DEV_ID_PCH_SPT_I219_LM2		0x15B7	/* SPT-H PCH */
++#define E1000_DEV_ID_PCH_SPT_I219_V2		0x15B8	/* SPT-H PCH */
+ 
+ #define E1000_REVISION_4	4
+ 
+@@ -108,6 +112,7 @@ enum e1000_mac_type {
+ 	e1000_pchlan,
+ 	e1000_pch2lan,
+ 	e1000_pch_lpt,
++	e1000_pch_spt,
+ };
+ 
+ enum e1000_media_type {
+@@ -153,6 +158,7 @@ enum e1000_bus_width {
+ 	e1000_bus_width_pcie_x1,
+ 	e1000_bus_width_pcie_x2,
+ 	e1000_bus_width_pcie_x4 = 4,
++	e1000_bus_width_pcie_x8 = 8,
+ 	e1000_bus_width_32,
+ 	e1000_bus_width_64,
+ 	e1000_bus_width_reserved
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+@@ -123,6 +123,14 @@ static s32 e1000_read_flash_word_ich8lan
+ 					 u16 *data);
+ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+ 					 u8 size, u16 *data);
++static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
++					   u32 *data);
++static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw,
++					  u32 offset, u32 *data);
++static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw,
++					    u32 offset, u32 data);
++static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
++						 u32 offset, u32 dword);
+ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
+ static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
+ static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);
+@@ -229,7 +237,8 @@ static bool e1000_phy_is_accessible_pchl
+ 	if (ret_val)
+ 		return false;
+ out:
+-	if (hw->mac.type == e1000_pch_lpt) {
++	if ((hw->mac.type == e1000_pch_lpt) ||
++	    (hw->mac.type == e1000_pch_spt)) {
+ 		/* Unforce SMBus mode in PHY */
+ 		e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
+ 		phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+@@ -321,6 +330,7 @@ static s32 e1000_init_phy_workarounds_pc
+ 	 */
+ 	switch (hw->mac.type) {
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 		if (e1000_phy_is_accessible_pchlan(hw))
+ 			break;
+ 
+@@ -461,6 +471,7 @@ static s32 e1000_init_phy_params_pchlan(
+ 			/* fall-through */
+ 		case e1000_pch2lan:
+ 		case e1000_pch_lpt:
++		case e1000_pch_spt:
+ 			/* In case the PHY needs to be in mdio slow mode,
+ 			 * set slow mode and try to get the PHY id again.
+ 			 */
+@@ -591,35 +602,50 @@ static s32 e1000_init_nvm_params_ich8lan
+ 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ 	u32 gfpreg, sector_base_addr, sector_end_addr;
+ 	u16 i;
++	u32 nvm_size;
+ 
+ 	/* Can't read flash registers if the register set isn't mapped. */
+-	if (!hw->flash_address) {
+-		e_dbg("ERROR: Flash registers not mapped\n");
+-		return -E1000_ERR_CONFIG;
+-	}
+-
+ 	nvm->type = e1000_nvm_flash_sw;
++	/* in SPT, gfpreg doesn't exist. NVM size is taken from the
++	 * STRAP register
++	 */
++	if (hw->mac.type == e1000_pch_spt) {
++		nvm->flash_base_addr = 0;
++		nvm_size = (((er32(STRAP) >> 1) & 0x1F) + 1)
++		    * NVM_SIZE_MULTIPLIER;
++		nvm->flash_bank_size = nvm_size / 2;
++		/* Adjust to word count */
++		nvm->flash_bank_size /= sizeof(u16);
++		/* Set the base address for flash register access */
++		hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
++	} else {
++		if (!hw->flash_address) {
++			e_dbg("ERROR: Flash registers not mapped\n");
++			return -E1000_ERR_CONFIG;
++		}
+ 
+-	gfpreg = er32flash(ICH_FLASH_GFPREG);
++		gfpreg = er32flash(ICH_FLASH_GFPREG);
+ 
+-	/* sector_X_addr is a "sector"-aligned address (4096 bytes)
+-	 * Add 1 to sector_end_addr since this sector is included in
+-	 * the overall size.
+-	 */
+-	sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+-	sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+-
+-	/* flash_base_addr is byte-aligned */
+-	nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+-
+-	/* find total size of the NVM, then cut in half since the total
+-	 * size represents two separate NVM banks.
+-	 */
+-	nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
+-				<< FLASH_SECTOR_ADDR_SHIFT);
+-	nvm->flash_bank_size /= 2;
+-	/* Adjust to word count */
+-	nvm->flash_bank_size /= sizeof(u16);
++		/* sector_X_addr is a "sector"-aligned address (4096 bytes)
++		 * Add 1 to sector_end_addr since this sector is included in
++		 * the overall size.
++		 */
++		sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
++		sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
++
++		/* flash_base_addr is byte-aligned */
++		nvm->flash_base_addr = sector_base_addr
++		    << FLASH_SECTOR_ADDR_SHIFT;
++
++		/* find total size of the NVM, then cut in half since the total
++		 * size represents two separate NVM banks.
++		 */
++		nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
++					<< FLASH_SECTOR_ADDR_SHIFT);
++		nvm->flash_bank_size /= 2;
++		/* Adjust to word count */
++		nvm->flash_bank_size /= sizeof(u16);
++	}
+ 
+ 	nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS;
+ 
+@@ -683,6 +709,7 @@ static s32 e1000_init_mac_params_ich8lan
+ 		mac->ops.rar_set = e1000_rar_set_pch2lan;
+ 		/* fall-through */
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 	case e1000_pchlan:
+ 		/* check management mode */
+ 		mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
+@@ -700,7 +727,7 @@ static s32 e1000_init_mac_params_ich8lan
+ 		break;
+ 	}
+ 
+-	if (mac->type == e1000_pch_lpt) {
++	if ((mac->type == e1000_pch_lpt) || (mac->type == e1000_pch_spt)) {
+ 		mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
+ 		mac->ops.rar_set = e1000_rar_set_pch_lpt;
+ 		mac->ops.setup_physical_interface =
+@@ -920,8 +947,9 @@ release:
+ 		/* clear FEXTNVM6 bit 8 on link down or 10/100 */
+ 		fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
+ 
+-		if (!link || ((status & E1000_STATUS_SPEED_100) &&
+-			      (status & E1000_STATUS_FD)))
++		if ((hw->phy.revision > 5) || !link ||
++		    ((status & E1000_STATUS_SPEED_100) &&
++		     (status & E1000_STATUS_FD)))
+ 			goto update_fextnvm6;
+ 
+ 		ret_val = e1e_rphy(hw, I217_INBAND_CTRL, &reg);
+@@ -1101,6 +1129,21 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000
+ 	if (ret_val)
+ 		goto out;
+ 
++	/* Si workaround for ULP entry flow on i127/rev6 h/w.  Enable
++	 * LPLU and disable Gig speed when entering ULP
++	 */
++	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
++		ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
++						       &phy_reg);
++		if (ret_val)
++			goto release;
++		phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
++		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
++							phy_reg);
++		if (ret_val)
++			goto release;
++	}
++
+ 	/* Force SMBus mode in PHY */
+ 	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
+ 	if (ret_val)
+@@ -1303,7 +1346,8 @@ out:
+ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
+ {
+ 	struct e1000_mac_info *mac = &hw->mac;
+-	s32 ret_val;
++	s32 ret_val, tipg_reg = 0;
++	u16 emi_addr, emi_val = 0;
+ 	bool link;
+ 	u16 phy_reg;
+ 
+@@ -1334,48 +1378,55 @@ static s32 e1000_check_for_copper_link_i
+ 	 * the IPG and reduce Rx latency in the PHY.
+ 	 */
+ 	if (((hw->mac.type == e1000_pch2lan) ||
+-	     (hw->mac.type == e1000_pch_lpt)) && link) {
++	     (hw->mac.type == e1000_pch_lpt) ||
++	     (hw->mac.type == e1000_pch_spt)) && link) {
+ 		u32 reg;
+ 
+ 		reg = er32(STATUS);
++		tipg_reg = er32(TIPG);
++		tipg_reg &= ~E1000_TIPG_IPGT_MASK;
++
+ 		if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
+-			u16 emi_addr;
++			tipg_reg |= 0xFF;
++			/* Reduce Rx latency in analog PHY */
++			emi_val = 0;
++		} else {
+ 
+-			reg = er32(TIPG);
+-			reg &= ~E1000_TIPG_IPGT_MASK;
+-			reg |= 0xFF;
+-			ew32(TIPG, reg);
++			/* Roll back the default values */
++			tipg_reg |= 0x08;
++			emi_val = 1;
++		}
+ 
+-			/* Reduce Rx latency in analog PHY */
+-			ret_val = hw->phy.ops.acquire(hw);
+-			if (ret_val)
+-				return ret_val;
++		ew32(TIPG, tipg_reg);
+ 
+-			if (hw->mac.type == e1000_pch2lan)
+-				emi_addr = I82579_RX_CONFIG;
+-			else
+-				emi_addr = I217_RX_CONFIG;
++		ret_val = hw->phy.ops.acquire(hw);
++		if (ret_val)
++			return ret_val;
+ 
+-			ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);
++		if (hw->mac.type == e1000_pch2lan)
++			emi_addr = I82579_RX_CONFIG;
++		else
++			emi_addr = I217_RX_CONFIG;
++		ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
+ 
+-			hw->phy.ops.release(hw);
++		hw->phy.ops.release(hw);
+ 
+-			if (ret_val)
+-				return ret_val;
+-		}
++		if (ret_val)
++			return ret_val;
+ 	}
+ 
+ 	/* Work-around I218 hang issue */
+ 	if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+ 	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
+ 	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM3) ||
+-	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) {
++	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3) ||
++	    (hw->mac.type == e1000_pch_spt)) {
+ 		ret_val = e1000_k1_workaround_lpt_lp(hw, link);
+ 		if (ret_val)
+ 			return ret_val;
+ 	}
+-
+-	if (hw->mac.type == e1000_pch_lpt) {
++	if ((hw->mac.type == e1000_pch_lpt) ||
++	    (hw->mac.type == e1000_pch_spt)) {
+ 		/* Set platform power management values for
+ 		 * Latency Tolerance Reporting (LTR)
+ 		 */
+@@ -1387,6 +1438,19 @@ static s32 e1000_check_for_copper_link_i
+ 	/* Clear link partner's EEE ability */
+ 	hw->dev_spec.ich8lan.eee_lp_ability = 0;
+ 
++	/* FEXTNVM6 K1-off workaround */
++	if (hw->mac.type == e1000_pch_spt) {
++		u32 pcieanacfg = er32(PCIEANACFG);
++		u32 fextnvm6 = er32(FEXTNVM6);
++
++		if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
++			fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
++		else
++			fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
++
++		ew32(FEXTNVM6, fextnvm6);
++	}
++
+ 	if (!link)
+ 		return 0;	/* No link detected */
+ 
+@@ -1480,6 +1544,7 @@ static s32 e1000_get_variants_ich8lan(st
+ 	case e1000_pchlan:
+ 	case e1000_pch2lan:
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 		rc = e1000_init_phy_params_pchlan(hw);
+ 		break;
+ 	default:
+@@ -1930,6 +1995,7 @@ static s32 e1000_sw_lcd_config_ich8lan(s
+ 	case e1000_pchlan:
+ 	case e1000_pch2lan:
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
+ 		break;
+ 	default:
+@@ -2962,6 +3028,20 @@ static s32 e1000_valid_nvm_bank_detect_i
+ 	s32 ret_val;
+ 
+ 	switch (hw->mac.type) {
++		/* In SPT, read from the CTRL_EXT reg instead of
++		 * accessing the sector valid bits from the nvm
++		 */
++	case e1000_pch_spt:
++		*bank = er32(CTRL_EXT)
++		    & E1000_CTRL_EXT_NVMVS;
++		if ((*bank == 0) || (*bank == 1)) {
++			e_dbg("ERROR: No valid NVM bank present\n");
++			return -E1000_ERR_NVM;
++		} else {
++			*bank = *bank - 2;
++			return 0;
++		}
++		break;
+ 	case e1000_ich8lan:
+ 	case e1000_ich9lan:
+ 		eecd = er32(EECD);
+@@ -3009,6 +3089,99 @@ static s32 e1000_valid_nvm_bank_detect_i
+ }
+ 
+ /**
++ *  e1000_read_nvm_spt - NVM access for SPT
++ *  @hw: pointer to the HW structure
++ *  @offset: The offset (in bytes) of the word(s) to read.
++ *  @words: Size of data to read in words.
++ *  @data: pointer to the word(s) to read at offset.
++ *
++ *  Reads a word(s) from the NVM
++ **/
++static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
++			      u16 *data)
++{
++	struct e1000_nvm_info *nvm = &hw->nvm;
++	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
++	u32 act_offset;
++	s32 ret_val = 0;
++	u32 bank = 0;
++	u32 dword = 0;
++	u16 offset_to_read;
++	u16 i;
++
++	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
++	    (words == 0)) {
++		e_dbg("nvm parameter(s) out of bounds\n");
++		ret_val = -E1000_ERR_NVM;
++		goto out;
++	}
++
++	nvm->ops.acquire(hw);
++
++	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
++	if (ret_val) {
++		e_dbg("Could not detect valid bank, assuming bank 0\n");
++		bank = 0;
++	}
++
++	act_offset = (bank) ? nvm->flash_bank_size : 0;
++	act_offset += offset;
++
++	ret_val = 0;
++
++	for (i = 0; i < words; i += 2) {
++		if (words - i == 1) {
++			if (dev_spec->shadow_ram[offset + i].modified) {
++				data[i] =
++				    dev_spec->shadow_ram[offset + i].value;
++			} else {
++				offset_to_read = act_offset + i -
++				    ((act_offset + i) % 2);
++				ret_val =
++				  e1000_read_flash_dword_ich8lan(hw,
++								 offset_to_read,
++								 &dword);
++				if (ret_val)
++					break;
++				if ((act_offset + i) % 2 == 0)
++					data[i] = (u16)(dword & 0xFFFF);
++				else
++					data[i] = (u16)((dword >> 16) & 0xFFFF);
++			}
++		} else {
++			offset_to_read = act_offset + i;
++			if (!(dev_spec->shadow_ram[offset + i].modified) ||
++			    !(dev_spec->shadow_ram[offset + i + 1].modified)) {
++				ret_val =
++				  e1000_read_flash_dword_ich8lan(hw,
++								 offset_to_read,
++								 &dword);
++				if (ret_val)
++					break;
++			}
++			if (dev_spec->shadow_ram[offset + i].modified)
++				data[i] =
++				    dev_spec->shadow_ram[offset + i].value;
++			else
++				data[i] = (u16)(dword & 0xFFFF);
++			if (dev_spec->shadow_ram[offset + i].modified)
++				data[i + 1] =
++				    dev_spec->shadow_ram[offset + i + 1].value;
++			else
++				data[i + 1] = (u16)(dword >> 16 & 0xFFFF);
++		}
++	}
++
++	nvm->ops.release(hw);
++
++out:
++	if (ret_val)
++		e_dbg("NVM read error: %d\n", ret_val);
++
++	return ret_val;
++}
++
++/**
+  *  e1000_read_nvm_ich8lan - Read word(s) from the NVM
+  *  @hw: pointer to the HW structure
+  *  @offset: The offset (in bytes) of the word(s) to read.
+@@ -3091,8 +3264,10 @@ static s32 e1000_flash_cycle_init_ich8la
+ 	/* Clear FCERR and DAEL in hw status by writing 1 */
+ 	hsfsts.hsf_status.flcerr = 1;
+ 	hsfsts.hsf_status.dael = 1;
+-
+-	ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
++	if (hw->mac.type == e1000_pch_spt)
++		ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF);
++	else
++		ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ 
+ 	/* Either we should have a hardware SPI cycle in progress
+ 	 * bit to check against, in order to start a new cycle or
+@@ -3108,7 +3283,10 @@ static s32 e1000_flash_cycle_init_ich8la
+ 		 * Begin by setting Flash Cycle Done.
+ 		 */
+ 		hsfsts.hsf_status.flcdone = 1;
+-		ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
++		if (hw->mac.type == e1000_pch_spt)
++			ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF);
++		else
++			ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ 		ret_val = 0;
+ 	} else {
+ 		s32 i;
+@@ -3129,7 +3307,11 @@ static s32 e1000_flash_cycle_init_ich8la
+ 			 * now set the Flash Cycle Done.
+ 			 */
+ 			hsfsts.hsf_status.flcdone = 1;
+-			ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
++			if (hw->mac.type == e1000_pch_spt)
++				ew32flash(ICH_FLASH_HSFSTS,
++					  hsfsts.regval & 0xFFFF);
++			else
++				ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ 		} else {
+ 			e_dbg("Flash controller busy, cannot get access\n");
+ 		}
+@@ -3152,9 +3334,16 @@ static s32 e1000_flash_cycle_ich8lan(str
+ 	u32 i = 0;
+ 
+ 	/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
+-	hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
++	if (hw->mac.type == e1000_pch_spt)
++		hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16;
++	else
++		hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
+ 	hsflctl.hsf_ctrl.flcgo = 1;
+-	ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
++
++	if (hw->mac.type == e1000_pch_spt)
++		ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16);
++	else
++		ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+ 
+ 	/* wait till FDONE bit is set to 1 */
+ 	do {
+@@ -3171,6 +3360,23 @@ static s32 e1000_flash_cycle_ich8lan(str
+ }
+ 
+ /**
++ *  e1000_read_flash_dword_ich8lan - Read dword from flash
++ *  @hw: pointer to the HW structure
++ *  @offset: offset to data location
++ *  @data: pointer to the location for storing the data
++ *
++ *  Reads the flash dword at offset into data.  Offset is converted
++ *  to bytes before read.
++ **/
++static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset,
++					  u32 *data)
++{
++	/* Must convert word offset into bytes. */
++	offset <<= 1;
++	return e1000_read_flash_data32_ich8lan(hw, offset, data);
++}
++
++/**
+  *  e1000_read_flash_word_ich8lan - Read word from flash
+  *  @hw: pointer to the HW structure
+  *  @offset: offset to data location
+@@ -3202,7 +3408,14 @@ static s32 e1000_read_flash_byte_ich8lan
+ 	s32 ret_val;
+ 	u16 word = 0;
+ 
+-	ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
++	/* In SPT, only 32 bits access is supported,
++	 * so this function should not be called.
++	 */
++	if (hw->mac.type == e1000_pch_spt)
++		return -E1000_ERR_NVM;
++	else
++		ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
++
+ 	if (ret_val)
+ 		return ret_val;
+ 
+@@ -3288,6 +3501,82 @@ static s32 e1000_read_flash_data_ich8lan
+ }
+ 
+ /**
++ *  e1000_read_flash_data32_ich8lan - Read dword from NVM
++ *  @hw: pointer to the HW structure
++ *  @offset: The offset (in bytes) of the dword to read.
++ *  @data: Pointer to the dword to store the value read.
++ *
++ *  Reads a byte or word from the NVM using the flash access registers.
++ **/
++
++static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
++					   u32 *data)
++{
++	union ich8_hws_flash_status hsfsts;
++	union ich8_hws_flash_ctrl hsflctl;
++	u32 flash_linear_addr;
++	s32 ret_val = -E1000_ERR_NVM;
++	u8 count = 0;
++
++	if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
++	    hw->mac.type != e1000_pch_spt)
++		return -E1000_ERR_NVM;
++	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
++			     hw->nvm.flash_base_addr);
++
++	do {
++		udelay(1);
++		/* Steps */
++		ret_val = e1000_flash_cycle_init_ich8lan(hw);
++		if (ret_val)
++			break;
++		/* In SPT, This register is in Lan memory space, not flash.
++		 * Therefore, only 32 bit access is supported
++		 */
++		hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16;
++
++		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
++		hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
++		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
++		/* In SPT, This register is in Lan memory space, not flash.
++		 * Therefore, only 32 bit access is supported
++		 */
++		ew32flash(ICH_FLASH_HSFSTS, (u32)hsflctl.regval << 16);
++		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
++
++		ret_val =
++		   e1000_flash_cycle_ich8lan(hw,
++					     ICH_FLASH_READ_COMMAND_TIMEOUT);
++
++		/* Check if FCERR is set to 1, if set to 1, clear it
++		 * and try the whole sequence a few more times, else
++		 * read in (shift in) the Flash Data0, the order is
++		 * least significant byte first msb to lsb
++		 */
++		if (!ret_val) {
++			*data = er32flash(ICH_FLASH_FDATA0);
++			break;
++		} else {
++			/* If we've gotten here, then things are probably
++			 * completely hosed, but if the error condition is
++			 * detected, it won't hurt to give it another try...
++			 * ICH_FLASH_CYCLE_REPEAT_COUNT times.
++			 */
++			hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
++			if (hsfsts.hsf_status.flcerr) {
++				/* Repeat for some time before giving up. */
++				continue;
++			} else if (!hsfsts.hsf_status.flcdone) {
++				e_dbg("Timeout error - flash cycle did not complete.\n");
++				break;
++			}
++		}
++	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
++
++	return ret_val;
++}
++
++/**
+  *  e1000_write_nvm_ich8lan - Write word(s) to the NVM
+  *  @hw: pointer to the HW structure
+  *  @offset: The offset (in bytes) of the word(s) to write.
+@@ -3322,7 +3611,7 @@ static s32 e1000_write_nvm_ich8lan(struc
+ }
+ 
+ /**
+- *  e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
++ *  e1000_update_nvm_checksum_spt - Update the checksum for NVM
+  *  @hw: pointer to the HW structure
+  *
+  *  The NVM checksum is updated by calling the generic update_nvm_checksum,
+@@ -3332,13 +3621,13 @@ static s32 e1000_write_nvm_ich8lan(struc
+  *  After a successful commit, the shadow ram is cleared and is ready for
+  *  future writes.
+  **/
+-static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
++static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw)
+ {
+ 	struct e1000_nvm_info *nvm = &hw->nvm;
+ 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ 	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
+ 	s32 ret_val;
+-	u16 data;
++	u32 dword = 0;
+ 
+ 	ret_val = e1000e_update_nvm_checksum_generic(hw);
+ 	if (ret_val)
+@@ -3372,12 +3661,175 @@ static s32 e1000_update_nvm_checksum_ich
+ 		if (ret_val)
+ 			goto release;
+ 	}
+-
+-	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
++	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i += 2) {
+ 		/* Determine whether to write the value stored
+ 		 * in the other NVM bank or a modified value stored
+ 		 * in the shadow RAM
+ 		 */
++		ret_val = e1000_read_flash_dword_ich8lan(hw,
++							 i + old_bank_offset,
++							 &dword);
++
++		if (dev_spec->shadow_ram[i].modified) {
++			dword &= 0xffff0000;
++			dword |= (dev_spec->shadow_ram[i].value & 0xffff);
++		}
++		if (dev_spec->shadow_ram[i + 1].modified) {
++			dword &= 0x0000ffff;
++			dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff)
++				  << 16);
++		}
++		if (ret_val)
++			break;
++
++		/* If the word is 0x13, then make sure the signature bits
++		 * (15:14) are 11b until the commit has completed.
++		 * This will allow us to write 10b which indicates the
++		 * signature is valid.  We want to do this after the write
++		 * has completed so that we don't mark the segment valid
++		 * while the write is still in progress
++		 */
++		if (i == E1000_ICH_NVM_SIG_WORD - 1)
++			dword |= E1000_ICH_NVM_SIG_MASK << 16;
++
++		/* Convert offset to bytes. */
++		act_offset = (i + new_bank_offset) << 1;
++
++		usleep_range(100, 200);
++
++		/* Write the data to the new bank. Offset in words */
++		act_offset = i + new_bank_offset;
++		ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset,
++								dword);
++		if (ret_val)
++			break;
++	}
++
++	/* Don't bother writing the segment valid bits if sector
++	 * programming failed.
++	 */
++	if (ret_val) {
++		/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
++		e_dbg("Flash commit failed.\n");
++		goto release;
++	}
++
++	/* Finally validate the new segment by setting bit 15:14
++	 * to 10b in word 0x13 , this can be done without an
++	 * erase as well since these bits are 11 to start with
++	 * and we need to change bit 14 to 0b
++	 */
++	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
++
++	/*offset in words but we read dword */
++	--act_offset;
++	ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
++
++	if (ret_val)
++		goto release;
++
++	dword &= 0xBFFFFFFF;
++	ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
++
++	if (ret_val)
++		goto release;
++
++	/* And invalidate the previously valid segment by setting
++	 * its signature word (0x13) high_byte to 0b. This can be
++	 * done without an erase because flash erase sets all bits
++	 * to 1's. We can write 1's to 0's without an erase
++	 */
++	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
++
++	/* offset in words but we read dword */
++	act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1;
++	ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
++
++	if (ret_val)
++		goto release;
++
++	dword &= 0x00FFFFFF;
++	ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
++
++	if (ret_val)
++		goto release;
++
++	/* Great!  Everything worked, we can now clear the cached entries. */
++	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
++		dev_spec->shadow_ram[i].modified = false;
++		dev_spec->shadow_ram[i].value = 0xFFFF;
++	}
++
++release:
++	nvm->ops.release(hw);
++
++	/* Reload the EEPROM, or else modifications will not appear
++	 * until after the next adapter reset.
++	 */
++	if (!ret_val) {
++		nvm->ops.reload(hw);
++		usleep_range(10000, 20000);
++	}
++
++out:
++	if (ret_val)
++		e_dbg("NVM update error: %d\n", ret_val);
++
++	return ret_val;
++}
++
++/**
++ *  e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
++ *  @hw: pointer to the HW structure
++ *
++ *  The NVM checksum is updated by calling the generic update_nvm_checksum,
++ *  which writes the checksum to the shadow ram.  The changes in the shadow
++ *  ram are then committed to the EEPROM by processing each bank at a time
++ *  checking for the modified bit and writing only the pending changes.
++ *  After a successful commit, the shadow ram is cleared and is ready for
++ *  future writes.
++ **/
++static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
++{
++	struct e1000_nvm_info *nvm = &hw->nvm;
++	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
++	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
++	s32 ret_val;
++	u16 data = 0;
++
++	ret_val = e1000e_update_nvm_checksum_generic(hw);
++	if (ret_val)
++		goto out;
++
++	if (nvm->type != e1000_nvm_flash_sw)
++		goto out;
++
++	nvm->ops.acquire(hw);
++
++	/* We're writing to the opposite bank so if we're on bank 1,
++	 * write to bank 0 etc.  We also need to erase the segment that
++	 * is going to be written
++	 */
++	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
++	if (ret_val) {
++		e_dbg("Could not detect valid bank, assuming bank 0\n");
++		bank = 0;
++	}
++
++	if (bank == 0) {
++		new_bank_offset = nvm->flash_bank_size;
++		old_bank_offset = 0;
++		ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
++		if (ret_val)
++			goto release;
++	} else {
++		old_bank_offset = nvm->flash_bank_size;
++		new_bank_offset = 0;
++		ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
++		if (ret_val)
++			goto release;
++	}
++	for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
+ 		if (dev_spec->shadow_ram[i].modified) {
+ 			data = dev_spec->shadow_ram[i].value;
+ 		} else {
+@@ -3499,6 +3951,7 @@ static s32 e1000_validate_nvm_checksum_i
+ 	 */
+ 	switch (hw->mac.type) {
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 		word = NVM_COMPAT;
+ 		valid_csum_mask = NVM_COMPAT_VALID_CSUM;
+ 		break;
+@@ -3584,9 +4037,13 @@ static s32 e1000_write_flash_data_ich8la
+ 	s32 ret_val;
+ 	u8 count = 0;
+ 
+-	if (size < 1 || size > 2 || data > size * 0xff ||
+-	    offset > ICH_FLASH_LINEAR_ADDR_MASK)
+-		return -E1000_ERR_NVM;
++	if (hw->mac.type == e1000_pch_spt) {
++		if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
++			return -E1000_ERR_NVM;
++	} else {
++		if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
++			return -E1000_ERR_NVM;
++	}
+ 
+ 	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+ 			     hw->nvm.flash_base_addr);
+@@ -3597,12 +4054,25 @@ static s32 e1000_write_flash_data_ich8la
+ 		ret_val = e1000_flash_cycle_init_ich8lan(hw);
+ 		if (ret_val)
+ 			break;
++		/* In SPT, This register is in Lan memory space, not
++		 * flash.  Therefore, only 32 bit access is supported
++		 */
++		if (hw->mac.type == e1000_pch_spt)
++			hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16;
++		else
++			hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
+ 
+-		hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
+ 		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
+ 		hsflctl.hsf_ctrl.fldbcount = size - 1;
+ 		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
+-		ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
++		/* In SPT, This register is in Lan memory space,
++		 * not flash.  Therefore, only 32 bit access is
++		 * supported
++		 */
++		if (hw->mac.type == e1000_pch_spt)
++			ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16);
++		else
++			ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+ 
+ 		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
+ 
+@@ -3641,6 +4111,90 @@ static s32 e1000_write_flash_data_ich8la
+ }
+ 
+ /**
++*  e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM
++*  @hw: pointer to the HW structure
++*  @offset: The offset (in bytes) of the dwords to read.
++*  @data: The 4 bytes to write to the NVM.
++*
++*  Writes one/two/four bytes to the NVM using the flash access registers.
++**/
++static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
++					    u32 data)
++{
++	union ich8_hws_flash_status hsfsts;
++	union ich8_hws_flash_ctrl hsflctl;
++	u32 flash_linear_addr;
++	s32 ret_val;
++	u8 count = 0;
++
++	if (hw->mac.type == e1000_pch_spt) {
++		if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
++			return -E1000_ERR_NVM;
++	}
++	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
++			     hw->nvm.flash_base_addr);
++	do {
++		udelay(1);
++		/* Steps */
++		ret_val = e1000_flash_cycle_init_ich8lan(hw);
++		if (ret_val)
++			break;
++
++		/* In SPT, This register is in Lan memory space, not
++		 * flash.  Therefore, only 32 bit access is supported
++		 */
++		if (hw->mac.type == e1000_pch_spt)
++			hsflctl.regval = er32flash(ICH_FLASH_HSFSTS)
++			    >> 16;
++		else
++			hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
++
++		hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
++		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
++
++		/* In SPT, This register is in Lan memory space,
++		 * not flash.  Therefore, only 32 bit access is
++		 * supported
++		 */
++		if (hw->mac.type == e1000_pch_spt)
++			ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16);
++		else
++			ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
++
++		ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
++
++		ew32flash(ICH_FLASH_FDATA0, data);
++
++		/* check if FCERR is set to 1 , if set to 1, clear it
++		 * and try the whole sequence a few more times else done
++		 */
++		ret_val =
++		   e1000_flash_cycle_ich8lan(hw,
++					     ICH_FLASH_WRITE_COMMAND_TIMEOUT);
++
++		if (!ret_val)
++			break;
++
++		/* If we're here, then things are most likely
++		 * completely hosed, but if the error condition
++		 * is detected, it won't hurt to give it another
++		 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
++		 */
++		hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
++
++		if (hsfsts.hsf_status.flcerr)
++			/* Repeat for some time before giving up. */
++			continue;
++		if (!hsfsts.hsf_status.flcdone) {
++			e_dbg("Timeout error - flash cycle did not complete.\n");
++			break;
++		}
++	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
++
++	return ret_val;
++}
++
++/**
+  *  e1000_write_flash_byte_ich8lan - Write a single byte to NVM
+  *  @hw: pointer to the HW structure
+  *  @offset: The index of the byte to read.
+@@ -3657,6 +4211,40 @@ static s32 e1000_write_flash_byte_ich8la
+ }
+ 
+ /**
++*  e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM
++*  @hw: pointer to the HW structure
++*  @offset: The offset of the word to write.
++*  @dword: The dword to write to the NVM.
++*
++*  Writes a single dword to the NVM using the flash access registers.
++*  Goes through a retry algorithm before giving up.
++**/
++static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
++						 u32 offset, u32 dword)
++{
++	s32 ret_val;
++	u16 program_retries;
++
++	/* Must convert word offset into bytes. */
++	offset <<= 1;
++	ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
++
++	if (!ret_val)
++		return ret_val;
++	for (program_retries = 0; program_retries < 100; program_retries++) {
++		e_dbg("Retrying Byte %8.8X at offset %u\n", dword, offset);
++		usleep_range(100, 200);
++		ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
++		if (!ret_val)
++			break;
++	}
++	if (program_retries == 100)
++		return -E1000_ERR_NVM;
++
++	return 0;
++}
++
++/**
+  *  e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
+  *  @hw: pointer to the HW structure
+  *  @offset: The offset of the byte to write.
+@@ -3760,9 +4348,18 @@ static s32 e1000_erase_flash_bank_ich8la
+ 			/* Write a value 11 (block Erase) in Flash
+ 			 * Cycle field in hw flash control
+ 			 */
+-			hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
++			if (hw->mac.type == e1000_pch_spt)
++				hsflctl.regval =
++				    er32flash(ICH_FLASH_HSFSTS) >> 16;
++			else
++				hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
++
+ 			hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
+-			ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
++			if (hw->mac.type == e1000_pch_spt)
++				ew32flash(ICH_FLASH_HSFSTS,
++					  hsflctl.regval << 16);
++			else
++				ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+ 
+ 			/* Write the last 24 bits of an index within the
+ 			 * block into Flash Linear address field in Flash
+@@ -4181,7 +4778,8 @@ static void e1000_initialize_hw_bits_ich
+ 	ew32(RFCTL, reg);
+ 
+ 	/* Enable ECC on Lynxpoint */
+-	if (hw->mac.type == e1000_pch_lpt) {
++	if ((hw->mac.type == e1000_pch_lpt) ||
++	    (hw->mac.type == e1000_pch_spt)) {
+ 		reg = er32(PBECCSTS);
+ 		reg |= E1000_PBECCSTS_ECC_ENABLE;
+ 		ew32(PBECCSTS, reg);
+@@ -4584,7 +5182,8 @@ void e1000_suspend_workarounds_ich8lan(s
+ 		if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+ 		    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
+ 		    (device_id == E1000_DEV_ID_PCH_I218_LM3) ||
+-		    (device_id == E1000_DEV_ID_PCH_I218_V3)) {
++		    (device_id == E1000_DEV_ID_PCH_I218_V3) ||
++		    (hw->mac.type == e1000_pch_spt)) {
+ 			u32 fextnvm6 = er32(FEXTNVM6);
+ 
+ 			ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+@@ -5045,6 +5644,17 @@ static const struct e1000_nvm_operations
+ 	.write			= e1000_write_nvm_ich8lan,
+ };
+ 
++static const struct e1000_nvm_operations spt_nvm_ops = {
++	.acquire		= e1000_acquire_nvm_ich8lan,
++	.release		= e1000_release_nvm_ich8lan,
++	.read			= e1000_read_nvm_spt,
++	.update			= e1000_update_nvm_checksum_spt,
++	.reload			= e1000e_reload_nvm_generic,
++	.valid_led_default	= e1000_valid_led_default_ich8lan,
++	.validate		= e1000_validate_nvm_checksum_ich8lan,
++	.write			= e1000_write_nvm_ich8lan,
++};
++
+ const struct e1000_info e1000_ich8_info = {
+ 	.mac			= e1000_ich8lan,
+ 	.flags			= FLAG_HAS_WOL
+@@ -5153,3 +5763,23 @@ const struct e1000_info e1000_pch_lpt_in
+ 	.phy_ops		= &ich8_phy_ops,
+ 	.nvm_ops		= &ich8_nvm_ops,
+ };
++
++const struct e1000_info e1000_pch_spt_info = {
++	.mac			= e1000_pch_spt,
++	.flags			= FLAG_IS_ICH
++				  | FLAG_HAS_WOL
++				  | FLAG_HAS_HW_TIMESTAMP
++				  | FLAG_HAS_CTRLEXT_ON_LOAD
++				  | FLAG_HAS_AMT
++				  | FLAG_HAS_FLASH
++				  | FLAG_HAS_JUMBO_FRAMES
++				  | FLAG_APME_IN_WUC,
++	.flags2			= FLAG2_HAS_PHY_STATS
++				  | FLAG2_HAS_EEE,
++	.pba			= 26,
++	.max_hw_frame_size	= 9018,
++	.get_variants		= e1000_get_variants_ich8lan,
++	.mac_ops		= &ich8_mac_ops,
++	.phy_ops		= &ich8_phy_ops,
++	.nvm_ops		= &spt_nvm_ops,
++};
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
+@@ -95,9 +95,18 @@
+ 
+ #define E1000_FEXTNVM6_REQ_PLL_CLK	0x00000100
+ #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION	0x00000200
++#define E1000_FEXTNVM6_K1_OFF_ENABLE	0x80000000
++/* bit for disabling packet buffer read */
++#define E1000_FEXTNVM7_DISABLE_PB_READ	0x00040000
+ 
+ #define E1000_FEXTNVM7_DISABLE_SMB_PERST	0x00000020
+ 
++#define K1_ENTRY_LATENCY	0
++#define K1_MIN_TIME		1
++#define NVM_SIZE_MULTIPLIER 4096	/*multiplier for NVMS field */
++#define E1000_FLASH_BASE_ADDR 0xE000	/*offset of NVM access regs */
++#define E1000_CTRL_EXT_NVMVS 0x3	/*NVM valid sector */
++
+ #define PCIE_ICH8_SNOOP_ALL	PCIE_NO_SNOOP_ALL
+ 
+ #define E1000_ICH_RAR_ENTRIES	7
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -70,6 +70,7 @@ static const struct e1000_info *e1000_in
+ 	[board_pchlan]		= &e1000_pch_info,
+ 	[board_pch2lan]		= &e1000_pch2_info,
+ 	[board_pch_lpt]		= &e1000_pch_lpt_info,
++	[board_pch_spt]		= &e1000_pch_spt_info,
+ };
+ 
+ struct e1000_reg_info {
+@@ -1796,7 +1797,8 @@ static irqreturn_t e1000_intr_msi(int __
+ 	}
+ 
+ 	/* Reset on uncorrectable ECC error */
+-	if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
++	if ((icr & E1000_ICR_ECCER) && ((hw->mac.type == e1000_pch_lpt) ||
++					(hw->mac.type == e1000_pch_spt))) {
+ 		u32 pbeccsts = er32(PBECCSTS);
+ 
+ 		adapter->corr_errors +=
+@@ -1876,7 +1878,8 @@ static irqreturn_t e1000_intr(int __alwa
+ 	}
+ 
+ 	/* Reset on uncorrectable ECC error */
+-	if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
++	if ((icr & E1000_ICR_ECCER) && ((hw->mac.type == e1000_pch_lpt) ||
++					(hw->mac.type == e1000_pch_spt))) {
+ 		u32 pbeccsts = er32(PBECCSTS);
+ 
+ 		adapter->corr_errors +=
+@@ -2257,7 +2260,8 @@ static void e1000_irq_enable(struct e100
+ 	if (adapter->msix_entries) {
+ 		ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
+ 		ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
+-	} else if (hw->mac.type == e1000_pch_lpt) {
++	} else if ((hw->mac.type == e1000_pch_lpt) ||
++		   (hw->mac.type == e1000_pch_spt)) {
+ 		ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
+ 	} else {
+ 		ew32(IMS, IMS_ENABLE_MASK);
+@@ -3014,6 +3018,19 @@ static void e1000_configure_tx(struct e1
+ 	ew32(TCTL, tctl);
+ 
+ 	hw->mac.ops.config_collision_dist(hw);
++
++	/* SPT Si errata workaround to avoid data corruption */
++	if (hw->mac.type == e1000_pch_spt) {
++		u32 reg_val;
++
++		reg_val = er32(IOSFPC);
++		reg_val |= E1000_RCTL_RDMTS_HEX;
++		ew32(IOSFPC, reg_val);
++
++		reg_val = er32(TARC(0));
++		reg_val |= E1000_TARC0_CB_MULTIQ_3_REQ;
++		ew32(TARC(0), reg_val);
++	}
+ }
+ 
+ /**
+@@ -3493,8 +3510,11 @@ s32 e1000e_get_base_timinca(struct e1000
+ 	struct e1000_hw *hw = &adapter->hw;
+ 	u32 incvalue, incperiod, shift;
+ 
+-	/* Make sure clock is enabled on I217 before checking the frequency */
+-	if ((hw->mac.type == e1000_pch_lpt) &&
++	/* Make sure clock is enabled on I217/I218/I219  before checking
++	 * the frequency
++	 */
++	if (((hw->mac.type == e1000_pch_lpt) ||
++	     (hw->mac.type == e1000_pch_spt)) &&
+ 	    !(er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) &&
+ 	    !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_ENABLED)) {
+ 		u32 fextnvm7 = er32(FEXTNVM7);
+@@ -3508,10 +3528,13 @@ s32 e1000e_get_base_timinca(struct e1000
+ 	switch (hw->mac.type) {
+ 	case e1000_pch2lan:
+ 	case e1000_pch_lpt:
+-		/* On I217, the clock frequency is 25MHz or 96MHz as
+-		 * indicated by the System Clock Frequency Indication
++	case e1000_pch_spt:
++		/* On I217, I218 and I219, the clock frequency is 25MHz
++		 * or 96MHz as indicated by the System Clock Frequency
++		 * Indication
+ 		 */
+-		if ((hw->mac.type != e1000_pch_lpt) ||
++		if (((hw->mac.type != e1000_pch_lpt) &&
++		     (hw->mac.type != e1000_pch_spt)) ||
+ 		    (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) {
+ 			/* Stable 96MHz frequency */
+ 			incperiod = INCPERIOD_96MHz;
+@@ -3878,6 +3901,7 @@ void e1000e_reset(struct e1000_adapter *
+ 		break;
+ 	case e1000_pch2lan:
+ 	case e1000_pch_lpt:
++	case e1000_pch_spt:
+ 		fc->refresh_time = 0x0400;
+ 
+ 		if (adapter->netdev->mtu <= ETH_DATA_LEN) {
+@@ -4762,7 +4786,8 @@ static void e1000e_update_stats(struct e
+ 	adapter->stats.mgpdc += er32(MGTPDC);
+ 
+ 	/* Correctable ECC Errors */
+-	if (hw->mac.type == e1000_pch_lpt) {
++	if ((hw->mac.type == e1000_pch_lpt) ||
++	    (hw->mac.type == e1000_pch_spt)) {
+ 		u32 pbeccsts = er32(PBECCSTS);
+ 
+ 		adapter->corr_errors +=
+@@ -6125,7 +6150,8 @@ static int __e1000_shutdown(struct pci_d
+ 
+ 	if (adapter->hw.phy.type == e1000_phy_igp_3) {
+ 		e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
+-	} else if (hw->mac.type == e1000_pch_lpt) {
++	} else if ((hw->mac.type == e1000_pch_lpt) ||
++		   (hw->mac.type == e1000_pch_spt)) {
+ 		if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
+ 			/* ULP does not support wake from unicast, multicast
+ 			 * or broadcast.
+@@ -7177,6 +7203,10 @@ static const struct pci_device_id e1000_
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V2), board_pch_lpt },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM3), board_pch_lpt },
+ 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V3), board_pch_lpt },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM), board_pch_spt },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V), board_pch_spt },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM2), board_pch_spt },
++	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V2), board_pch_spt },
+ 
+ 	{ 0, 0, 0, 0, 0, 0, 0 }	/* terminate list */
+ };
+--- a/drivers/net/ethernet/intel/e1000e/ptp.c
++++ b/drivers/net/ethernet/intel/e1000e/ptp.c
+@@ -224,7 +224,9 @@ void e1000e_ptp_init(struct e1000_adapte
+ 	switch (hw->mac.type) {
+ 	case e1000_pch2lan:
+ 	case e1000_pch_lpt:
+-		if ((hw->mac.type != e1000_pch_lpt) ||
++	case e1000_pch_spt:
++		if (((hw->mac.type != e1000_pch_lpt) &&
++		     (hw->mac.type != e1000_pch_spt)) ||
+ 		    (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) {
+ 			adapter->ptp_clock_info.max_adj = 24000000 - 1;
+ 			break;
+--- a/drivers/net/ethernet/intel/e1000e/regs.h
++++ b/drivers/net/ethernet/intel/e1000e/regs.h
+@@ -38,6 +38,7 @@
+ #define E1000_FEXTNVM4	0x00024	/* Future Extended NVM 4 - RW */
+ #define E1000_FEXTNVM6	0x00010	/* Future Extended NVM 6 - RW */
+ #define E1000_FEXTNVM7	0x000E4	/* Future Extended NVM 7 - RW */
++#define E1000_PCIEANACFG	0x00F18	/* PCIE Analog Config */
+ #define E1000_FCT	0x00030	/* Flow Control Type - RW */
+ #define E1000_VET	0x00038	/* VLAN Ether Type - RW */
+ #define E1000_ICR	0x000C0	/* Interrupt Cause Read - R/clr */
+@@ -67,6 +68,7 @@
+ #define E1000_PBA	0x01000	/* Packet Buffer Allocation - RW */
+ #define E1000_PBS	0x01008	/* Packet Buffer Size */
+ #define E1000_PBECCSTS	0x0100C	/* Packet Buffer ECC Status - RW */
++#define E1000_IOSFPC	0x00F28	/* TX corrupted data  */
+ #define E1000_EEMNGCTL	0x01010	/* MNG EEprom Control */
+ #define E1000_EEWR	0x0102C	/* EEPROM Write Register - RW */
+ #define E1000_FLOP	0x0103C	/* FLASH Opcode Register */
+@@ -121,6 +123,7 @@
+ 				 (0x054E4 + ((_i - 16) * 8)))
+ #define E1000_SHRAL(_i)		(0x05438 + ((_i) * 8))
+ #define E1000_SHRAH(_i)		(0x0543C + ((_i) * 8))
++#define E1000_TARC0_CB_MULTIQ_3_REQ	(1 << 28 | 1 << 29)
+ #define E1000_TDFH		0x03410	/* Tx Data FIFO Head - RW */
+ #define E1000_TDFT		0x03418	/* Tx Data FIFO Tail - RW */
+ #define E1000_TDFHS		0x03420	/* Tx Data FIFO Head Saved - RW */

Added: dists/jessie/linux/debian/patches/features/all/e1000e/0002-e1000e-fix-obscure-comments.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/jessie/linux/debian/patches/features/all/e1000e/0002-e1000e-fix-obscure-comments.patch	Sat May 23 17:15:21 2015	(r22681)
@@ -0,0 +1,48 @@
+From: Yanir Lubetkin <yanirx.lubetkin at intel.com>
+Date: Sat, 28 Feb 2015 10:09:34 +0000
+Subject: e1000e: fix obscure comments
+Origin: https://git.kernel.org/linus/9d17ce493a3ef1b140a4c831ba72fb435576c75a
+Bug-Debian: https://bugs.debian.org/784546
+
+The interface to the device flash was modified in i219 and later HW.
+This patch better describes the change and the impact on the driver.
+
+CC: John W Linville <linville at tuxdriver.com>
+Reported-by: John W Linville <linville at tuxdriver.com>
+Signed-off-by: Yanir Lubetkin <yanirx.lubetkin at intel.com>
+Tested-by: Aaron Brown <aaron.f.brown at intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
+---
+ drivers/net/ethernet/intel/e1000e/ich8lan.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+@@ -604,12 +604,15 @@ static s32 e1000_init_nvm_params_ich8lan
+ 	u16 i;
+ 	u32 nvm_size;
+ 
+-	/* Can't read flash registers if the register set isn't mapped. */
+ 	nvm->type = e1000_nvm_flash_sw;
+-	/* in SPT, gfpreg doesn't exist. NVM size is taken from the
+-	 * STRAP register
+-	 */
++
+ 	if (hw->mac.type == e1000_pch_spt) {
++		/* in SPT, gfpreg doesn't exist. NVM size is taken from the
++		 * STRAP register. This is because in SPT the GbE Flash region
++		 * is no longer accessed through the flash registers. Instead,
++		 * the mechanism has changed, and the Flash region access
++		 * registers are now implemented in GbE memory space.
++		 */
+ 		nvm->flash_base_addr = 0;
+ 		nvm_size = (((er32(STRAP) >> 1) & 0x1F) + 1)
+ 		    * NVM_SIZE_MULTIPLIER;
+@@ -619,6 +622,7 @@ static s32 e1000_init_nvm_params_ich8lan
+ 		/* Set the base address for flash register access */
+ 		hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
+ 	} else {
++		/* Can't read flash registers if register set isn't mapped. */
+ 		if (!hw->flash_address) {
+ 			e_dbg("ERROR: Flash registers not mapped\n");
+ 			return -E1000_ERR_CONFIG;

Added: dists/jessie/linux/debian/patches/features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/jessie/linux/debian/patches/features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch	Sat May 23 17:15:21 2015	(r22681)
@@ -0,0 +1,50 @@
+From: Yanir Lubetkin <yanirx.lubetkin at intel.com>
+Date: Sat, 28 Feb 2015 10:10:06 +0000
+Subject: e1000e: remove calls to ioremap/unmap for NVM addr
+Origin: https://git.kernel.org/linus/1103a631a83408733849b47fa2170cda984df2a3
+Bug-Debian: https://bugs.debian.org/784546
+
+Starting I219, the NVM will not be mapped to its own BAR, but to an
+address region in another bar.  The mapping/unmapping is relevant
+to older HW only.
+
+CC: John W Linville <linville at tuxdriver.com>
+Reported-by: John W Linville <linville at tuxdriver.com>
+Signed-off-by: Yanir Lubetkin <yanirx.lubetkin at intel.com>
+Tested-by: Aaron Brown <aaron.f.brown at intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
+---
+ drivers/net/ethernet/intel/e1000e/netdev.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -6806,7 +6806,8 @@ static int e1000_probe(struct pci_dev *p
+ 		goto err_ioremap;
+ 
+ 	if ((adapter->flags & FLAG_HAS_FLASH) &&
+-	    (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
++	    (pci_resource_flags(pdev, 1) & IORESOURCE_MEM) &&
++	    (hw->mac.type < e1000_pch_spt)) {
+ 		flash_start = pci_resource_start(pdev, 1);
+ 		flash_len = pci_resource_len(pdev, 1);
+ 		adapter->hw.flash_address = ioremap(flash_start, flash_len);
+@@ -7033,7 +7034,7 @@ err_hw_init:
+ 	kfree(adapter->tx_ring);
+ 	kfree(adapter->rx_ring);
+ err_sw_init:
+-	if (adapter->hw.flash_address)
++	if ((adapter->hw.flash_address) && (hw->mac.type < e1000_pch_spt))
+ 		iounmap(adapter->hw.flash_address);
+ 	e1000e_reset_interrupt_capability(adapter);
+ err_flashmap:
+@@ -7106,7 +7107,8 @@ static void e1000_remove(struct pci_dev
+ 	kfree(adapter->rx_ring);
+ 
+ 	iounmap(adapter->hw.hw_addr);
+-	if (adapter->hw.flash_address)
++	if ((adapter->hw.flash_address) &&
++	    (adapter->hw.mac.type < e1000_pch_spt))
+ 		iounmap(adapter->hw.flash_address);
+ 	pci_release_selected_regions(pdev,
+ 				     pci_select_bars(pdev, IORESOURCE_MEM));

Added: dists/jessie/linux/debian/patches/features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/jessie/linux/debian/patches/features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch	Sat May 23 17:15:21 2015	(r22681)
@@ -0,0 +1,30 @@
+From: Yanir Lubetkin <yanirx.lubetkin at intel.com>
+Date: Fri, 20 Mar 2015 17:41:53 -0700
+Subject: e1000e: NVM write protect access removed from SPT HW
+Origin: https://git.kernel.org/linus/152c0a976c71386c67c89969acc427dc5cf802b8
+Bug-Debian: https://bugs.debian.org/784546
+
+The call to e1000e_write_protect_nvm_ich8lan() is no longer supported by HW.
+Access to these registers causes a system freeze in A step hardware and is
+ignored in B step hardware. This function must not be called in hardware
+newer than LPT.
+
+Signed-off-by: Yanir Lubetkin <yanirx.lubetkin at intel.com>
+Tested-by: Aaron Brown <aaron.f.brown at intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
+---
+ drivers/net/ethernet/intel/e1000e/netdev.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -6847,7 +6847,8 @@ static int e1000_probe(struct pci_dev *p
+ 		goto err_hw_init;
+ 
+ 	if ((adapter->flags & FLAG_IS_ICH) &&
+-	    (adapter->flags & FLAG_READ_ONLY_NVM))
++	    (adapter->flags & FLAG_READ_ONLY_NVM) &&
++	    (hw->mac.type < e1000_pch_spt))
+ 		e1000e_write_protect_nvm_ich8lan(&adapter->hw);
+ 
+ 	hw->mac.ops.get_bus_info(&adapter->hw);

Modified: dists/jessie/linux/debian/patches/series
==============================================================================
--- dists/jessie/linux/debian/patches/series	Sat May 23 17:12:46 2015	(r22680)
+++ dists/jessie/linux/debian/patches/series	Sat May 23 17:15:21 2015	(r22681)
@@ -585,6 +585,12 @@
 features/all/psmouse/input-psmouse-disable-changing-resolution-rate-scale.patch
 features/all/psmouse/input-psmouse-disable-palm-detection-in-the-focaltec.patch
 
+# Add i219 support to e1000e
+features/all/e1000e/0001-e1000e-initial-support-for-i219.patch
+features/all/e1000e/0002-e1000e-fix-obscure-comments.patch
+features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch
+features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch
+
 # Fix ABI changes
 debian/of-fix-abi-changes.patch
 debian/iovec-fix-abi-change-in-3.16.7-ckt1.patch



More information about the Kernel-svn-changes mailing list