diff --git a/debian/changelog b/debian/changelog index c721c4816..c20b7f07a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -145,6 +145,7 @@ linux (4.0.4-1) UNRELEASED; urgency=medium - Add support for ACPI identification to xhci-platform * md/raid0: fix restore to sector variable in raid0_make_request (Closes: #786372) (regression in 4.0.2) + * [x86] e1000e: Add support for Sunrise Point (i219) (Closes: #784546) -- Ben Hutchings Mon, 18 May 2015 00:00:06 +0100 diff --git a/debian/patches/features/all/e1000e/0001-e1000e-initial-support-for-i219.patch b/debian/patches/features/all/e1000e/0001-e1000e-initial-support-for-i219.patch new file mode 100644 index 000000000..fc23628c8 --- /dev/null +++ b/debian/patches/features/all/e1000e/0001-e1000e-initial-support-for-i219.patch @@ -0,0 +1,1363 @@ +From: David Ertman +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 +Tested-by: Aaron Brown +Tested-by: Carmen Edwards +Signed-off-by: Jeff Kirsher +--- + 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. + */ +@@ -590,35 +601,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; + +@@ -682,6 +708,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; +@@ -699,7 +726,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 = +@@ -919,8 +946,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, ®); +@@ -1100,6 +1128,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) +@@ -1302,7 +1345,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; + +@@ -1333,48 +1377,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) + */ +@@ -1386,6 +1437,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 */ + +@@ -1479,6 +1543,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: +@@ -1929,6 +1994,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: +@@ -2961,6 +3027,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); +@@ -3008,6 +3088,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. +@@ -3090,8 +3263,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 +@@ -3107,7 +3282,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; +@@ -3128,7 +3306,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"); + } +@@ -3151,9 +3333,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 { +@@ -3170,6 +3359,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 +@@ -3201,7 +3407,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; + +@@ -3287,6 +3500,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. +@@ -3321,7 +3610,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, +@@ -3331,13 +3620,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) +@@ -3371,12 +3660,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 { +@@ -3498,6 +3950,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; +@@ -3583,9 +4036,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); +@@ -3596,12 +4053,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); + +@@ -3640,6 +4110,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. +@@ -3656,6 +4210,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. +@@ -3759,9 +4347,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 +@@ -4180,7 +4777,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); +@@ -4583,7 +5181,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); +@@ -5058,6 +5657,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 +@@ -5166,3 +5776,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); ++ } + } + + /** +@@ -3490,8 +3507,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); +@@ -3505,10 +3525,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; +@@ -3875,6 +3898,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) { +@@ -4759,7 +4783,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 += +@@ -6144,7 +6169,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. +@@ -7213,6 +7239,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 +@@ -221,7 +221,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 */ diff --git a/debian/patches/features/all/e1000e/0002-e1000e-fix-obscure-comments.patch b/debian/patches/features/all/e1000e/0002-e1000e-fix-obscure-comments.patch new file mode 100644 index 000000000..6f870e5cc --- /dev/null +++ b/debian/patches/features/all/e1000e/0002-e1000e-fix-obscure-comments.patch @@ -0,0 +1,48 @@ +From: Yanir Lubetkin +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 +Reported-by: John W Linville +Signed-off-by: Yanir Lubetkin +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher +--- + 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 +@@ -603,12 +603,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; +@@ -618,6 +621,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; diff --git a/debian/patches/features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch b/debian/patches/features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch new file mode 100644 index 000000000..e7f241e11 --- /dev/null +++ b/debian/patches/features/all/e1000e/0003-e1000e-remove-calls-to-ioremap-unmap-for-nvm-addr.patch @@ -0,0 +1,50 @@ +From: Yanir Lubetkin +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 +Reported-by: John W Linville +Signed-off-by: Yanir Lubetkin +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher +--- + 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 +@@ -6833,7 +6833,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); +@@ -7069,7 +7070,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: +@@ -7142,7 +7143,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)); diff --git a/debian/patches/features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch b/debian/patches/features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch new file mode 100644 index 000000000..550bb8965 --- /dev/null +++ b/debian/patches/features/all/e1000e/0004-e1000e-nvm-write-protect-access-removed-from-spt-hw.patch @@ -0,0 +1,30 @@ +From: Yanir Lubetkin +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 +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher +--- + 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 +@@ -6874,7 +6874,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); diff --git a/debian/patches/series b/debian/patches/series index 7c244df5e..4dbc94068 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -71,3 +71,9 @@ bugfix/all/rtc-hctosys-use-function-name-in-the-error-log.patch features/arm64/usb-make-xhci-platform-driver-use-64-bit-or-32-bit-dma.patch features/arm64/usb-add-support-for-acpi-identification-to-xhci-platform.patch bugfix/all/md-raid0-fix-restore-to-sector-variable-in-raid0_make_request.patch + +# Add Sunrise Point 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