Commit cb79abc7 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next



Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates

This series contains updates to igb and e1000e.

Akeem provides 3 igb patches, the first resets the link when EEE is enabled
or disabled if the link is up.  His second patch changes a register read
which normally stores of the read value to "just-read" so that hardware
can accurately latch the register read.  Lastly, he adds rcu_lock to avoid
a possible race condition with igb_update_stats function.

Mitch provides a fix for SR-IOV, where MSI-X interrupts are required, so
make sure that MSI-X is enabled before allowing the user to turn on SR-IOV.

Alex's igb patch make it so that we limit the lower bound for max_frame_size
to the size of a standard Ethernet frame.  This allows for feature parity
with other Intel based drivers such as ixgbe.

Carolyn adds a SKU for a flashless i210 device and a fix for get_fw_version()
so that it works for all parts for igb.  In addition, she has 2 igb patches
to refactor NVM code to accommodate devices with no flash.  Lastly, she
adds code to check for the failure of pci_disable_link_state() to attempt
to work around a problem found with some systems.

Laura provides the remaining 2 igb patches.  One removing the hard-coded
value for the size of the RETA indirection table, and creates a macro instead
for the RETA indirection table.  The second adds the ethtool callbacks
necessary to change the RETA indirection table from userspace.

Bruce fixes a whitespace issue in a recent commit and resolves a jiffies
comparison warning by using time_after().

Li provides a fix for e1000e to avoid a kernel crash on shutdown by adding
one more check in e1000e_shutdown().  This is due to e1000e_shutdown()
trying to clear correctable errors on the upstream P2P bridge, when under
some cases we do not have the upstream P2P bridge.

v2:
 - fixed patch 11 conditional statement from < to <= based on feedback
   from Ben Hutchings
 - fixed patch 12 patch description (adding the commit summary) based
   on feedback from Sergei Shtylyov
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f8825669 22f8abaa
......@@ -1665,7 +1665,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
ret_val = 13; /* ret_val is the same as mis-compare */
break;
}
if (jiffies >= (time + 20)) {
if (time_after(jiffies, time + 20)) {
ret_val = 14; /* error code for time out error */
break;
}
......
......@@ -233,7 +233,8 @@ union e1000_rx_desc_extended {
#define MAX_PS_BUFFERS 4
/* Number of packet split data buffers (not including the header buffer) */
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
/* Receive Descriptor - Packet Split */
union e1000_rx_desc_packet_split {
struct {
......
......@@ -64,8 +64,6 @@ static int debug = -1;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
static const struct e1000_info *e1000_info_tbl[] = {
[board_82571] = &e1000_82571_info,
[board_82572] = &e1000_82572_info,
......@@ -6001,11 +5999,18 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
* correctable error when the MAC transitions from D0 to D3. To
* prevent this we need to mask off the correctable errors on the
* downstream port of the pci-e switch.
*
* We don't have the associated upstream bridge while assigning
* the PCI device into guest. For example, the KVM on power is
* one of the cases.
*/
if (adapter->flags & FLAG_IS_QUAD_PORT) {
struct pci_dev *us_dev = pdev->bus->self;
u16 devctl;
if (!us_dev)
return 0;
pcie_capability_read_word(us_dev, PCI_EXP_DEVCTL, &devctl);
pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL,
(devctl & ~PCI_EXP_DEVCTL_CERE));
......@@ -6019,38 +6024,73 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
return 0;
}
#ifdef CONFIG_PCIEASPM
static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
/**
* e1000e_disable_aspm - Disable ASPM states
* @pdev: pointer to PCI device struct
* @state: bit-mask of ASPM states to disable
*
* Some devices *must* have certain ASPM states disabled per hardware errata.
**/
static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
struct pci_dev *parent = pdev->bus->self;
u16 aspm_dis_mask = 0;
u16 pdev_aspmc, parent_aspmc;
switch (state) {
case PCIE_LINK_STATE_L0S:
case PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1:
aspm_dis_mask |= PCI_EXP_LNKCTL_ASPM_L0S;
/* fall-through - can't have L1 without L0s */
case PCIE_LINK_STATE_L1:
aspm_dis_mask |= PCI_EXP_LNKCTL_ASPM_L1;
break;
default:
return;
}
pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc);
pdev_aspmc &= PCI_EXP_LNKCTL_ASPMC;
if (parent) {
pcie_capability_read_word(parent, PCI_EXP_LNKCTL,
&parent_aspmc);
parent_aspmc &= PCI_EXP_LNKCTL_ASPMC;
}
/* Nothing to do if the ASPM states to be disabled already are */
if (!(pdev_aspmc & aspm_dis_mask) &&
(!parent || !(parent_aspmc & aspm_dis_mask)))
return;
dev_info(&pdev->dev, "Disabling ASPM %s %s\n",
(aspm_dis_mask & pdev_aspmc & PCI_EXP_LNKCTL_ASPM_L0S) ?
"L0s" : "",
(aspm_dis_mask & pdev_aspmc & PCI_EXP_LNKCTL_ASPM_L1) ?
"L1" : "");
#ifdef CONFIG_PCIEASPM
pci_disable_link_state_locked(pdev, state);
}
#else
static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
u16 aspm_ctl = 0;
if (state & PCIE_LINK_STATE_L0S)
aspm_ctl |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & PCIE_LINK_STATE_L1)
aspm_ctl |= PCI_EXP_LNKCTL_ASPM_L1;
/* Double-check ASPM control. If not disabled by the above, the
* BIOS is preventing that from happening (or CONFIG_PCIEASPM is
* not enabled); override by writing PCI config space directly.
*/
pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc);
pdev_aspmc &= PCI_EXP_LNKCTL_ASPMC;
if (!(aspm_dis_mask & pdev_aspmc))
return;
#endif
/* Both device and parent should have the same ASPM setting.
* Disable ASPM in downstream component first and then upstream.
*/
pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_ctl);
if (pdev->bus->self)
pcie_capability_clear_word(pdev->bus->self, PCI_EXP_LNKCTL,
aspm_ctl);
}
#endif
static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
dev_info(&pdev->dev, "Disabling ASPM %s %s\n",
(state & PCIE_LINK_STATE_L0S) ? "L0s" : "",
(state & PCIE_LINK_STATE_L1) ? "L1" : "");
pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_dis_mask);
__e1000e_disable_aspm(pdev, state);
if (parent)
pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
aspm_dis_mask);
}
#ifdef CONFIG_PM
......
......@@ -238,6 +238,7 @@ static s32 igb_init_nvm_params_82575(struct e1000_hw *hw)
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
E1000_EECD_SIZE_EX_SHIFT);
/* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
......@@ -250,86 +251,52 @@ static s32 igb_init_nvm_params_82575(struct e1000_hw *hw)
size = 15;
nvm->word_size = 1 << size;
if (hw->mac.type < e1000_i210) {
nvm->opcode_bits = 8;
nvm->delay_usec = 1;
switch (nvm->override) {
case e1000_nvm_override_spi_large:
nvm->page_size = 32;
nvm->address_bits = 16;
break;
case e1000_nvm_override_spi_small:
nvm->page_size = 8;
nvm->address_bits = 8;
break;
default:
nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
16 : 8;
break;
}
if (nvm->word_size == (1 << 15))
nvm->page_size = 128;
nvm->opcode_bits = 8;
nvm->delay_usec = 1;
nvm->type = e1000_nvm_eeprom_spi;
} else {
nvm->type = e1000_nvm_flash_hw;
switch (nvm->override) {
case e1000_nvm_override_spi_large:
nvm->page_size = 32;
nvm->address_bits = 16;
break;
case e1000_nvm_override_spi_small:
nvm->page_size = 8;
nvm->address_bits = 8;
break;
default:
nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
16 : 8;
break;
}
if (nvm->word_size == (1 << 15))
nvm->page_size = 128;
nvm->type = e1000_nvm_eeprom_spi;
/* NVM Function Pointers */
nvm->ops.acquire = igb_acquire_nvm_82575;
nvm->ops.release = igb_release_nvm_82575;
nvm->ops.write = igb_write_nvm_spi;
nvm->ops.validate = igb_validate_nvm_checksum;
nvm->ops.update = igb_update_nvm_checksum;
if (nvm->word_size < (1 << 15))
nvm->ops.read = igb_read_nvm_eerd;
else
nvm->ops.read = igb_read_nvm_spi;
/* override generic family function pointers for specific descendants */
switch (hw->mac.type) {
case e1000_82580:
nvm->ops.validate = igb_validate_nvm_checksum_82580;
nvm->ops.update = igb_update_nvm_checksum_82580;
nvm->ops.acquire = igb_acquire_nvm_82575;
nvm->ops.release = igb_release_nvm_82575;
if (nvm->word_size < (1 << 15))
nvm->ops.read = igb_read_nvm_eerd;
else
nvm->ops.read = igb_read_nvm_spi;
nvm->ops.write = igb_write_nvm_spi;
break;
case e1000_i354:
case e1000_i350:
nvm->ops.validate = igb_validate_nvm_checksum_i350;
nvm->ops.update = igb_update_nvm_checksum_i350;
nvm->ops.acquire = igb_acquire_nvm_82575;
nvm->ops.release = igb_release_nvm_82575;
if (nvm->word_size < (1 << 15))
nvm->ops.read = igb_read_nvm_eerd;
else
nvm->ops.read = igb_read_nvm_spi;
nvm->ops.write = igb_write_nvm_spi;
break;
case e1000_i210:
nvm->ops.validate = igb_validate_nvm_checksum_i210;
nvm->ops.update = igb_update_nvm_checksum_i210;
nvm->ops.acquire = igb_acquire_nvm_i210;
nvm->ops.release = igb_release_nvm_i210;
nvm->ops.read = igb_read_nvm_srrd_i210;
nvm->ops.write = igb_write_nvm_srwr_i210;
nvm->ops.valid_led_default = igb_valid_led_default_i210;
break;
case e1000_i211:
nvm->ops.acquire = igb_acquire_nvm_i210;
nvm->ops.release = igb_release_nvm_i210;
nvm->ops.read = igb_read_nvm_i211;
nvm->ops.valid_led_default = igb_valid_led_default_i210;
nvm->ops.validate = NULL;
nvm->ops.update = NULL;
nvm->ops.write = NULL;
break;
default:
nvm->ops.validate = igb_validate_nvm_checksum;
nvm->ops.update = igb_update_nvm_checksum;
nvm->ops.acquire = igb_acquire_nvm_82575;
nvm->ops.release = igb_release_nvm_82575;
if (nvm->word_size < (1 << 15))
nvm->ops.read = igb_read_nvm_eerd;
else
nvm->ops.read = igb_read_nvm_spi;
nvm->ops.write = igb_write_nvm_spi;
break;
}
......@@ -516,6 +483,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_I210_FIBER:
case E1000_DEV_ID_I210_SERDES:
case E1000_DEV_ID_I210_SGMII:
case E1000_DEV_ID_I210_COPPER_FLASHLESS:
case E1000_DEV_ID_I210_SERDES_FLASHLESS:
mac->type = e1000_i210;
break;
case E1000_DEV_ID_I211_COPPER:
......@@ -601,6 +570,15 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
/* NVM initialization */
ret_val = igb_init_nvm_params_82575(hw);
switch (hw->mac.type) {
case e1000_i210:
case e1000_i211:
ret_val = igb_init_nvm_params_i210(hw);
break;
default:
break;
}
if (ret_val)
goto out;
......@@ -1320,7 +1298,7 @@ void igb_shutdown_serdes_link_82575(struct e1000_hw *hw)
**/
static s32 igb_reset_hw_82575(struct e1000_hw *hw)
{
u32 ctrl, icr;
u32 ctrl;
s32 ret_val;
/* Prevent the PCI-E bus from sticking if there is no TLP connection
......@@ -1365,7 +1343,7 @@ static s32 igb_reset_hw_82575(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
wr32(E1000_IMC, 0xffffffff);
icr = rd32(E1000_ICR);
rd32(E1000_ICR);
/* Install any alternate MAC address into RAR0 */
ret_val = igb_check_alt_mac_addr(hw);
......@@ -2103,10 +2081,9 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
s32 ret_val = 0;
/* BH SW mailbox bit in SW_FW_SYNC */
u16 swmbsw_mask = E1000_SW_SYNCH_MB;
u32 ctrl, icr;
u32 ctrl;
bool global_device_reset = hw->dev_spec._82575.global_device_reset;
hw->dev_spec._82575.global_device_reset = false;
/* due to hw errata, global device reset doesn't always
......@@ -2165,7 +2142,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
wr32(E1000_IMC, 0xffffffff);
icr = rd32(E1000_ICR);
rd32(E1000_ICR);
ret_val = igb_reset_mdicnfg_82580(hw);
if (ret_val)
......
......@@ -620,6 +620,7 @@
#define E1000_EECD_SIZE_EX_SHIFT 11
#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
#define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */
#define E1000_FLUDONE_ATTEMPTS 20000
#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
#define E1000_I210_FIFO_SEL_RX 0x00
......@@ -627,6 +628,11 @@
#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
#define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */
/* Secure FLASH mode requires removing MSb */
#define E1000_I210_FW_PTR_MASK 0x7FFF
/* Firmware code revision field word offset*/
#define E1000_I210_FW_VER_OFFSET 328
#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
#define E1000_FLUDONE_ATTEMPTS 20000
......@@ -665,20 +671,26 @@
#define NVM_INIT_CTRL_4 0x0013
#define NVM_LED_1_CFG 0x001C
#define NVM_LED_0_2_CFG 0x001F
/* NVM version defines */
#define NVM_ETRACK_WORD 0x0042
#define NVM_ETRACK_HIWORD 0x0043
#define NVM_COMB_VER_OFF 0x0083
#define NVM_COMB_VER_PTR 0x003d
#define NVM_MAJOR_MASK 0xF000
#define NVM_MINOR_MASK 0x0FF0
#define NVM_BUILD_MASK 0x000F
#define NVM_COMB_VER_MASK 0x00FF
#define NVM_MAJOR_SHIFT 12
#define NVM_MINOR_SHIFT 4
#define NVM_COMB_VER_SHFT 8
#define NVM_VER_INVALID 0xFFFF
#define NVM_ETRACK_SHIFT 16
/* NVM version defines */
#define NVM_MAJOR_MASK 0xF000
#define NVM_MINOR_MASK 0x0FF0
#define NVM_IMAGE_ID_MASK 0x000F
#define NVM_COMB_VER_MASK 0x00FF
#define NVM_MAJOR_SHIFT 12
#define NVM_MINOR_SHIFT 4
#define NVM_COMB_VER_SHFT 8
#define NVM_VER_INVALID 0xFFFF
#define NVM_ETRACK_SHIFT 16
#define NVM_ETRACK_VALID 0x8000
#define NVM_NEW_DEC_MASK 0x0F00
#define NVM_HEX_CONV 16
#define NVM_HEX_TENS 10
#define NVM_ETS_CFG 0x003E
#define NVM_ETS_LTHRES_DELTA_MASK 0x07C0
#define NVM_ETS_LTHRES_DELTA_SHIFT 6
......
......@@ -67,6 +67,8 @@ struct e1000_hw;
#define E1000_DEV_ID_I210_FIBER 0x1536
#define E1000_DEV_ID_I210_SERDES 0x1537
#define E1000_DEV_ID_I210_SGMII 0x1538
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
#define E1000_DEV_ID_I211_COPPER 0x1539
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
#define E1000_DEV_ID_I354_SGMII 0x1F41
......@@ -110,6 +112,7 @@ enum e1000_nvm_type {
e1000_nvm_none,
e1000_nvm_eeprom_spi,
e1000_nvm_flash_hw,
e1000_nvm_invm,
e1000_nvm_flash_sw
};
......
......@@ -335,57 +335,101 @@ s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
}
/**
* igb_read_nvm_i211 - Read NVM wrapper function for I211
* igb_read_invm_word_i210 - Reads OTP
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Reads 16-bit words from the OTP. Return error when the word is not
* stored in OTP.
**/
static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
{
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u32 invm_dword;
u16 i;
u8 record_type, word_address;
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = rd32(E1000_INVM_DATA_REG(i));
/* Get record type */
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
break;
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
if (word_address == address) {
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
hw_dbg("Read INVM Word 0x%02x = %x",
address, *data);
status = E1000_SUCCESS;
break;
}
}
}
if (status != E1000_SUCCESS)
hw_dbg("Requested word 0x%02x not found in OTP\n", address);
return status;
}
/**
* igb_read_invm_i210 - Read invm wrapper function for I210/I211
* @hw: pointer to the HW structure
* @words: number of words to read
* @data: pointer to the data read
*
* Wrapper function to return data formerly found in the NVM.
**/
s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data)
static s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset,
u16 words __always_unused, u16 *data)
{
s32 ret_val = E1000_SUCCESS;
/* Only the MAC addr is required to be present in the iNVM */
switch (offset) {
case NVM_MAC_ADDR:
ret_val = igb_read_invm_i211(hw, offset, &data[0]);
ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]);
ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]);
ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]);
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1,
&data[1]);
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2,
&data[2]);
if (ret_val != E1000_SUCCESS)
hw_dbg("MAC Addr not found in iNVM\n");
break;
case NVM_INIT_CTRL_2:
ret_val = igb_read_invm_i211(hw, (u8)offset, data);
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_2_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_INIT_CTRL_4:
ret_val = igb_read_invm_i211(hw, (u8)offset, data);
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_4_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_1_CFG:
ret_val = igb_read_invm_i211(hw, (u8)offset, data);
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_1_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_0_2_CFG:
igb_read_invm_i211(hw, offset, data);
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_0_2_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_ID_LED_SETTINGS:
ret_val = igb_read_invm_i211(hw, (u8)offset, data);
ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = ID_LED_RESERVED_FFFF;
ret_val = E1000_SUCCESS;
......@@ -410,48 +454,6 @@ s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
return ret_val;
}
/**
* igb_read_invm_i211 - Reads OTP
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Reads 16-bit words from the OTP. Return error when the word is not
* stored in OTP.
**/
s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
{
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u32 invm_dword;
u16 i;
u8 record_type, word_address;
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = rd32(E1000_INVM_DATA_REG(i));
/* Get record type */
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
break;
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
if (word_address == (u8)address) {
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
hw_dbg("Read INVM Word 0x%02x = %x",
address, *data);
status = E1000_SUCCESS;
break;
}
}
}
if (status != E1000_SUCCESS)
hw_dbg("Requested word 0x%02x not found in OTP\n", address);
return status;
}
/**
* igb_read_invm_version - Reads iNVM version and image type
* @hw: pointer to the HW structure
......@@ -660,6 +662,23 @@ static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
return ret_val;
}
/**
* igb_get_flash_presence_i210 - Check if flash device is detected.
* @hw: pointer to the HW structure
*
**/
bool igb_get_flash_presence_i210(struct e1000_hw *hw)
{
u32 eec = 0;
bool ret_val = false;
eec = rd32(E1000_EECD);
if (eec & E1000_EECD_FLASH_DETECTED_I210)
ret_val = true;
return ret_val;
}
/**
* igb_update_flash_i210 - Commit EEPROM to the flash
* @hw: pointer to the HW structure
......@@ -786,3 +805,33 @@ s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
{
return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false);
}
/**
* igb_init_nvm_params_i210 - Init NVM func ptrs.
* @hw: pointer to the HW structure
**/
s32 igb_init_nvm_params_i210(struct e1000_hw *hw)
{
s32 ret_val = 0;
struct e1000_nvm_info *nvm = &hw->nvm;
nvm->ops.acquire = igb_acquire_nvm_i210;
nvm->ops.release = igb_release_nvm_i210;