diff options
Diffstat (limited to 'sys/dev/e1000/e1000_ich8lan.c')
-rw-r--r-- | sys/dev/e1000/e1000_ich8lan.c | 88 |
1 files changed, 71 insertions, 17 deletions
diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index fdd5172..b2882ee 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -75,6 +75,9 @@ static void e1000_release_nvm_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); +static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw, + u8 *mc_addr_list, + u32 mc_addr_count); static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw); static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw); static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); @@ -213,7 +216,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) * the interconnect to PCIe mode. */ fwsm = E1000_READ_REG(hw, E1000_FWSM); - if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) { + if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && + !(hw->phy.ops.check_reset_block(hw))) { ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; @@ -540,6 +544,9 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) case e1000_pch2lan: mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch2lan; + /* multicast address update for pch2 */ + mac->ops.update_mc_addr_list = + e1000_update_mc_addr_list_pch2lan; /* fall-through */ case e1000_pchlan: /* save PCH revision_id */ @@ -835,8 +842,13 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_release_swflag_ich8lan"); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); + + if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) { + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; + E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); + } else { + DEBUGOUT("Semaphore unexpectedly released by sw/fw/hw\n"); + } E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); @@ -942,6 +954,34 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) } /** + * e1000_update_mc_addr_list_pch2lan - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * + * Updates entire Multicast Table Array of the PCH2 MAC and PHY. + * The caller must have a packed mc_addr_list of multicast addresses. + **/ +static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw, + u8 *mc_addr_list, + u32 mc_addr_count) +{ + int i; + + DEBUGFUNC("e1000_update_mc_addr_list_pch2lan"); + + e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count); + + for (i = 0; i < hw->mac.mta_reg_count; i++) { + hw->phy.ops.write_reg(hw, BM_MTA(i), + (u16)(hw->mac.mta_shadow[i] & 0xFFFF)); + hw->phy.ops.write_reg(hw, (BM_MTA(i) + 1), + (u16)((hw->mac.mta_shadow[i] >> 16) & + 0xFFFF)); + } +} + +/** * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked * @hw: pointer to the HW structure * @@ -1482,13 +1522,11 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; - ret_val = hw->phy.ops.read_reg_locked(hw, - PHY_REG(BM_PORT_CTRL_PAGE, 17), + ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG_REG, &phy_data); if (ret_val) goto release; - ret_val = hw->phy.ops.write_reg_locked(hw, - PHY_REG(BM_PORT_CTRL_PAGE, 17), + ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG_REG, phy_data & 0x00FF); release: hw->phy.ops.release(hw); @@ -1773,7 +1811,7 @@ out: /** * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware * @hw: pointer to the HW structure - * @gate: boolean set to TRUE to gate, FALSE to un-gate + * @gate: boolean set to TRUE to gate, FALSE to ungate * * Gate/ungate the automatic PHY configuration via hardware; perform * the configuration via software instead. @@ -1911,11 +1949,26 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) /* Configure the LCD with the OEM bits in NVM */ ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE); - /* Ungate automatic PHY configuration on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) { - msec_delay(10); - e1000_gate_hw_phy_config_ich8lan(hw, FALSE); + if (hw->mac.type == e1000_pch2lan) { + /* Ungate automatic PHY configuration on non-managed 82579 */ + if (!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_ICH_FWSM_FW_VALID)) { + msec_delay(10); + e1000_gate_hw_phy_config_ich8lan(hw, FALSE); + } + + /* Set EEE LPI Update Timer to 200usec */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, + I82579_LPI_UPDATE_TIMER); + if (ret_val) + goto release; + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, + 0x1387); +release: + hw->phy.ops.release(hw); } out: @@ -2323,7 +2376,6 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) { union ich8_hws_flash_status hsfsts; s32 ret_val = -E1000_ERR_NVM; - s32 i = 0; DEBUGFUNC("e1000_flash_cycle_init_ich8lan"); @@ -2361,6 +2413,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); ret_val = E1000_SUCCESS; } else { + s32 i; + /* * Otherwise poll for sometime so the current * cycle has a chance to end before giving up. @@ -3198,7 +3252,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u16 reg; - u32 ctrl, icr, kab; + u32 ctrl, kab; s32 ret_val; DEBUGFUNC("e1000_reset_hw_ich8lan"); @@ -3290,7 +3344,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_CRC_OFFSET, 0x65656565); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - icr = E1000_READ_REG(hw, E1000_ICR); + E1000_READ_REG(hw, E1000_ICR); kab = E1000_READ_REG(hw, E1000_KABGTXD); kab |= E1000_KABGTXD_BGSQLBIAS; @@ -3665,7 +3719,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); - if (!(dev_spec->kmrn_lock_loss_workaround_enabled)) + if (!dev_spec->kmrn_lock_loss_workaround_enabled) goto out; /* |