aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Li <chrisl@vmware.com>2008-09-05 17:04:05 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-09-18 21:40:24 -0400
commit78566fecbb12a7616ae9a88b2ffbc8062c4a89e3 (patch)
tree732e81889c6be0780ac196163a5c7c29f2dc490e
parentf55c21fd9a92a444e55ad1ca4e4732d56661bf2e (diff)
e1000: prevent corruption of EEPROM/NVM
Andrey reports e1000 corruption, and that a patch in vmware's ESX fixed it. The EEPROM corruption is triggered by concurrent access of the EEPROM read/write. Putting a lock around it solve the problem. [akpm@linux-foundation.org: use DEFINE_SPINLOCK to avoid confusing lockdep] Signed-off-by: Christopher Li <chrisl@vmware.com> Reported-by: Andrey Borzenkov <arvidjaar@mail.ru> Cc: Zach Amsden <zach@vmware.com> Cc: Pratap Subrahmanyam <pratap@vmware.com> Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Cc: Jesse Brandeburg <jesse.brandeburg@intel.com> Cc: Bruce Allan <bruce.w.allan@intel.com> Cc: PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com> Cc: John Ronciak <john.ronciak@intel.com> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/net/e1000/e1000_hw.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 9d6edf3e73f9..d04eef53571e 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -144,6 +144,8 @@ static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
144static u8 e1000_calculate_mng_checksum(char *buffer, u32 length); 144static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
145static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex); 145static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex);
146static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw); 146static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
147static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
148static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
147 149
148/* IGP cable length table */ 150/* IGP cable length table */
149static const 151static const
@@ -168,6 +170,8 @@ u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
168 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 170 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
169 104, 109, 114, 118, 121, 124}; 171 104, 109, 114, 118, 121, 124};
170 172
173static DEFINE_SPINLOCK(e1000_eeprom_lock);
174
171/****************************************************************************** 175/******************************************************************************
172 * Set the phy type member in the hw struct. 176 * Set the phy type member in the hw struct.
173 * 177 *
@@ -4904,6 +4908,15 @@ static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
4904 *****************************************************************************/ 4908 *****************************************************************************/
4905s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) 4909s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
4906{ 4910{
4911 s32 ret;
4912 spin_lock(&e1000_eeprom_lock);
4913 ret = e1000_do_read_eeprom(hw, offset, words, data);
4914 spin_unlock(&e1000_eeprom_lock);
4915 return ret;
4916}
4917
4918static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
4919{
4907 struct e1000_eeprom_info *eeprom = &hw->eeprom; 4920 struct e1000_eeprom_info *eeprom = &hw->eeprom;
4908 u32 i = 0; 4921 u32 i = 0;
4909 4922
@@ -5236,6 +5249,16 @@ s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
5236 *****************************************************************************/ 5249 *****************************************************************************/
5237s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) 5250s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
5238{ 5251{
5252 s32 ret;
5253 spin_lock(&e1000_eeprom_lock);
5254 ret = e1000_do_write_eeprom(hw, offset, words, data);
5255 spin_unlock(&e1000_eeprom_lock);
5256 return ret;
5257}
5258
5259
5260static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
5261{
5239 struct e1000_eeprom_info *eeprom = &hw->eeprom; 5262 struct e1000_eeprom_info *eeprom = &hw->eeprom;
5240 s32 status = 0; 5263 s32 status = 0;
5241 5264