summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2012-12-05 06:25:47 +0000
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-01-15 21:31:41 -0800
commit635ab56439e21cbea6be346ac71222f9c4ac6463 (patch)
treea29b0299e539fb7b6eb11d456a3b500ffe122524
parent1241f29fa3c6fa95f20e3e77452f8d6d60deae7a (diff)
e1000e: Acquire/release semaphore when writing each EEPROM page
When data blocks are written to the EEPROM, the HW/SW/FW semaphore must be held for the duration. With large data blocks on 80003es2lan, 82571 and 82572, this can take too long and cause the firmware to take ownership of the semaphore and consequently ownership of writes to the EEPROM. Instead, acquire and release the semaphore for each page of the block written. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/e1000e/nvm.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c
index b6468804cb2..71938ed2d3c 100644
--- a/drivers/net/ethernet/intel/e1000e/nvm.c
+++ b/drivers/net/ethernet/intel/e1000e/nvm.c
@@ -359,7 +359,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
- s32 ret_val;
+ s32 ret_val = -E1000_ERR_NVM;
u16 widx = 0;
/* A check for invalid values: offset too large, too many words,
@@ -371,16 +371,18 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
return -E1000_ERR_NVM;
}
- ret_val = nvm->ops.acquire(hw);
- if (ret_val)
- return ret_val;
-
while (widx < words) {
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
- ret_val = e1000_ready_nvm_eeprom(hw);
+ ret_val = nvm->ops.acquire(hw);
if (ret_val)
- goto release;
+ return ret_val;
+
+ ret_val = e1000_ready_nvm_eeprom(hw);
+ if (ret_val) {
+ nvm->ops.release(hw);
+ return ret_val;
+ }
e1000_standby_nvm(hw);
@@ -413,12 +415,10 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
break;
}
}
+ usleep_range(10000, 20000);
+ nvm->ops.release(hw);
}
- usleep_range(10000, 20000);
-release:
- nvm->ops.release(hw);
-
return ret_val;
}