On Tuesday 03 May 2011 15:18:06 Matthias Teege wrote:
> It probes every interface from 0 to 6 with a message like this:
>
> mmio_start: 0xfbde0000
> mmio_len: 0x00020000
> adapter->hw.hw_addr: ...
> adapter->max.typ: ...
> 00:10:f3:...
> e100e_probe succeeded!
>
> and then dies with
>
> err.alloc.etherdev
Thanks. I think I've found the culprit, which is that the e1000e driver
allocates around 16kB per e1000e interface. This appears to be for the
purpose of shadowing part of the non-volatile memory on ICH8 devices. As far
as I can tell, this functionality is wholly redundant in iPXE, and is present
only because the e1000e driver was ported from Linux rather than being created
as a dedicated iPXE driver.
The attached patch (compile-tested only) removes all references to this
shadowed RAM. Let me know if it fixes your problem.
Michael
diff --git a/src/drivers/net/e1000e/e1000e_hw.h b/src/drivers/net/e1000e/e1000e_hw.h
index 03ed35c..07b506a 100644
--- a/src/drivers/net/e1000e/e1000e_hw.h
+++ b/src/drivers/net/e1000e/e1000e_hw.h
@@ -666,16 +666,8 @@ struct e1000_dev_spec_80003es2lan {
bool mdic_wa_enable;
};
-struct e1000_shadow_ram {
- u16 value;
- bool modified;
-};
-
-#define E1000_ICH8_SHADOW_RAM_WORDS 2048
-
struct e1000_dev_spec_ich8lan {
bool kmrn_lock_loss_workaround_enabled;
- struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
bool nvm_k1_enabled;
};
diff --git a/src/drivers/net/e1000e/e1000e_ich8lan.c b/src/drivers/net/e1000e/e1000e_ich8lan.c
index 7b9a49b..ad90e81 100644
--- a/src/drivers/net/e1000e/e1000e_ich8lan.c
+++ b/src/drivers/net/e1000e/e1000e_ich8lan.c
@@ -360,12 +360,6 @@ static s32 e1000e_init_nvm_params_ich8lan(struct e1000_hw *hw)
nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS;
- /* Clear shadow ram */
- for (i = 0; i < nvm->word_size; i++) {
- dev_spec->shadow_ram[i].modified = false;
- dev_spec->shadow_ram[i].value = 0xFFFF;
- }
-
/* Function Pointers */
nvm->ops.acquire = e1000e_acquire_nvm_ich8lan;
nvm->ops.release = e1000e_release_nvm_ich8lan;
@@ -1599,17 +1593,12 @@ static s32 e1000e_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
ret_val = E1000_SUCCESS;
for (i = 0; i < words; i++) {
- if ((dev_spec->shadow_ram) &&
- (dev_spec->shadow_ram[offset+i].modified)) {
- data[i] = dev_spec->shadow_ram[offset+i].value;
- } else {
- ret_val = e1000e_read_flash_word_ich8lan(hw,
- act_offset + i,
- &word);
- if (ret_val)
- break;
- data[i] = word;
- }
+ ret_val = e1000e_read_flash_word_ich8lan(hw,
+ act_offset + i,
+ &word);
+ if (ret_val)
+ break;
+ data[i] = word;
}
nvm->ops.release(hw);
@@ -1871,31 +1860,11 @@ out:
*
* Writes a byte or word to the NVM using the flash access registers.
**/
-static s32 e1000e_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+static s32 e1000e_write_nvm_ich8lan(struct e1000_hw *hw __unused,
+ u16 offset __unused, u16 words __unused,
+ u16 *data __unused)
{
- struct e1000_nvm_info *nvm = &hw->nvm;
- struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- s32 ret_val = E1000_SUCCESS;
- 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);
-
- for (i = 0; i < words; i++) {
- dev_spec->shadow_ram[offset+i].modified = true;
- dev_spec->shadow_ram[offset+i].value = data[i];
- }
-
- nvm->ops.release(hw);
-
-out:
+ e_dbg("nvm write not supported\n");
return ret_val;
}
@@ -1910,162 +1879,9 @@ out:
* After a successful commit, the shadow ram is cleared and is ready for
* future writes.
**/
-static s32 e1000e_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+static s32 e1000e_update_nvm_checksum_ich8lan(struct e1000_hw *hw __unused)
{
- 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;
-
- 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 = e1000e_valid_nvm_bank_detect_ich8lan(hw, &bank);
- if (ret_val != E1000_SUCCESS) {
- 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 = e1000e_erase_flash_bank_ich8lan(hw, 1);
- if (ret_val) {
- nvm->ops.release(hw);
- goto out;
- }
- } else {
- old_bank_offset = nvm->flash_bank_size;
- new_bank_offset = 0;
- ret_val = e1000e_erase_flash_bank_ich8lan(hw, 0);
- if (ret_val) {
- nvm->ops.release(hw);
- goto out;
- }
- }
-
- for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
- /*
- * Determine whether to write the value stored
- * in the other NVM bank or a modified value stored
- * in the shadow RAM
- */
- if (dev_spec->shadow_ram[i].modified) {
- data = dev_spec->shadow_ram[i].value;
- } else {
- ret_val = e1000e_read_flash_word_ich8lan(hw, i +
- old_bank_offset,
- &data);
- 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)
- data |= E1000_ICH_NVM_SIG_MASK;
-
- /* Convert offset to bytes. */
- act_offset = (i + new_bank_offset) << 1;
-
- udelay(100);
- /* Write the bytes to the new bank. */
- ret_val = e1000e_retry_write_flash_byte_ich8lan(hw,
- act_offset,
- (u8)data);
- if (ret_val)
- break;
-
- udelay(100);
- ret_val = e1000e_retry_write_flash_byte_ich8lan(hw,
- act_offset + 1,
- (u8)(data >> 8));
- if (ret_val)
- break;
- }
-
- /*
- * Don't bother writing the segment valid bits if sector
- * programming failed.
- */
- if (ret_val) {
- e_dbg("Flash commit failed.\n");
- nvm->ops.release(hw);
- goto out;
- }
-
- /*
- * 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;
- ret_val = e1000e_read_flash_word_ich8lan(hw, act_offset, &data);
- if (ret_val) {
- nvm->ops.release(hw);
- goto out;
- }
-
- data &= 0xBFFF;
- ret_val = e1000e_retry_write_flash_byte_ich8lan(hw,
- act_offset * 2 + 1,
- (u8)(data >> 8));
- if (ret_val) {
- nvm->ops.release(hw);
- goto out;
- }
-
- /*
- * 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;
- ret_val = e1000e_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
- if (ret_val) {
- nvm->ops.release(hw);
- goto out;
- }
-
- /* 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;
- }
-
- nvm->ops.release(hw);
-
- /*
- * Reload the EEPROM, or else modifications will not appear
- * until after the next adapter reset.
- */
- nvm->ops.reload(hw);
- msleep(10);
-
-out:
- if (ret_val)
- e_dbg("NVM update error: %d\n", ret_val);
-
+ e_dbg("nvm write not supported\n");
return ret_val;
}
_______________________________________________
ipxe-devel mailing list
[email protected]
https://lists.ipxe.org/mailman/listinfo/ipxe-devel