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

Reply via email to