static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw)
{
	s32 ret_val = 0;
	u16 eeprom_regions_count = 1;
	u16 j, nvm_data;
	u16 nvm_offset;

	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
	if (ret_val) {
		hw_dbg("NVM Read Error\n");
		goto out;
	}

	if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
		eeprom_regions_count = 4;
	}

	for (j = 0; j < eeprom_regions_count; j++) {
		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
		ret_val = igb_validate_nvm_checksum_with_offset(hw,
								nvm_offset);
		if (ret_val != 0)
			goto out;
	}

out:
	return ret_val;
}
static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw)
{
	s32 ret_val;
	u16 j, nvm_data;
	u16 nvm_offset;

	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
	if (ret_val) {
		hw_dbg("NVM Read Error while updating checksum"
			" compatibility bit.\n");
		goto out;
	}

	if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) {
		
		nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
		ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
					&nvm_data);
		if (ret_val) {
			hw_dbg("NVM Write Error while updating checksum"
				" compatibility bit.\n");
			goto out;
		}
	}

	for (j = 0; j < 4; j++) {
		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
		ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset);
		if (ret_val)
			goto out;
	}

out:
	return ret_val;
}
static s32 igb_reset_mdicnfg_82580(struct e1000_hw *hw)
{
	s32 ret_val = 0;
	u32 mdicnfg;
	u16 nvm_data = 0;

	if (hw->mac.type != e1000_82580)
		goto out;
	if (!igb_sgmii_active_82575(hw))
		goto out;

	ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
				   NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
				   &nvm_data);
	if (ret_val) {
		hw_dbg("NVM Read Error\n");
		goto out;
	}

	mdicnfg = rd32(E1000_MDICNFG);
	if (nvm_data & NVM_WORD24_EXT_MDIO)
		mdicnfg |= E1000_MDICNFG_EXT_MDIO;
	if (nvm_data & NVM_WORD24_COM_MDIO)
		mdicnfg |= E1000_MDICNFG_COM_MDIO;
	wr32(E1000_MDICNFG, mdicnfg);
out:
	return ret_val;
}
static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw)
{
	s32 ret_val = 0;
	u16 j;
	u16 nvm_offset;

	for (j = 0; j < 4; j++) {
		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
		ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset);
		if (ret_val != 0)
			goto out;
	}

out:
	return ret_val;
}
/**
 *  igb_shutdown_serdes_link_82575 - Remove link during power down
 *  @hw: pointer to the HW structure
 *
 *  In the case of fiber serdes, shut down optics and PCS on driver unload
 *  when management pass thru is not enabled.
 **/
void igb_shutdown_serdes_link_82575(struct e1000_hw *hw)
{
	u32 reg;
	u16 eeprom_data = 0;

	if (hw->phy.media_type != e1000_media_type_internal_serdes ||
	    igb_sgmii_active_82575(hw))
		return;

	if (hw->bus.func == E1000_FUNC_0)
		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
	else if (hw->mac.type == e1000_82580)
		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
		                 NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
		                 &eeprom_data);
	else if (hw->bus.func == E1000_FUNC_1)
		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);

	/*
	 * If APM is not enabled in the EEPROM and management interface is
	 * not enabled, then power down.
	 */
	if (!(eeprom_data & E1000_NVM_APME_82575) &&
	    !igb_enable_mng_pass_thru(hw)) {
		/* Disable PCS to turn off link */
		reg = rd32(E1000_PCS_CFG0);
		reg &= ~E1000_PCS_CFG_PCS_EN;
		wr32(E1000_PCS_CFG0, reg);

		/* shutdown the laser */
		reg = rd32(E1000_CTRL_EXT);
		reg |= E1000_CTRL_EXT_SDP3_DATA;
		wr32(E1000_CTRL_EXT, reg);

		/* flush the write to verify completion */
		wrfl();
		msleep(1);
	}

	return;
}