aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2009-08-07 03:41:56 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-10 00:45:38 -0400
commit148675a7b2061b5a5eb194530b7c4d8de1f2887e (patch)
tree0b89a22585215699357afad86f4850bf9c2f28fd /drivers
parent373a88d78be540c1331ea5adcb76610dddcb008b (diff)
e1000e: fix potential NVM corruption on ICH9 with 8K bank size
The bank offset was being incorrectly calculated on ICH9 parts with a bank size of 8K (instead of the more common 4K bank) which would cause any NVM writes to be done on the wrong address after switching from bank 1 to bank 0. Additionally, assume we are meant to use bank 0 if a valid bank is not detected, and remove the unnecessary acquisition of the SW/FW/HW semaphore when writing to the shadow ram version of the NVM image. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/e1000e/ich8lan.c50
1 files changed, 12 insertions, 38 deletions
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index dd61e7e98ddb..99df2abf82a9 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -338,10 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
338{ 338{
339 struct e1000_nvm_info *nvm = &hw->nvm; 339 struct e1000_nvm_info *nvm = &hw->nvm;
340 struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 340 struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
341 union ich8_hws_flash_status hsfsts; 341 u32 gfpreg, sector_base_addr, sector_end_addr;
342 u32 gfpreg;
343 u32 sector_base_addr;
344 u32 sector_end_addr;
345 u16 i; 342 u16 i;
346 343
347 /* Can't read flash registers if the register set isn't mapped. */ 344 /* Can't read flash registers if the register set isn't mapped. */
@@ -375,20 +372,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
375 /* Adjust to word count */ 372 /* Adjust to word count */
376 nvm->flash_bank_size /= sizeof(u16); 373 nvm->flash_bank_size /= sizeof(u16);
377 374
378 /*
379 * Make sure the flash bank size does not overwrite the 4k
380 * sector ranges. We may have 64k allotted to us but we only care
381 * about the first 2 4k sectors. Therefore, if we have anything less
382 * than 64k set in the HSFSTS register, we will reduce the bank size
383 * down to 4k and let the rest remain unused. If berasesz == 3, then
384 * we are working in 64k mode. Otherwise we are not.
385 */
386 if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) {
387 hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
388 if (hsfsts.hsf_status.berasesz != 3)
389 nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS;
390 }
391
392 nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; 375 nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS;
393 376
394 /* Clear shadow ram */ 377 /* Clear shadow ram */
@@ -1324,7 +1307,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
1324 struct e1000_nvm_info *nvm = &hw->nvm; 1307 struct e1000_nvm_info *nvm = &hw->nvm;
1325 struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 1308 struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
1326 u32 act_offset; 1309 u32 act_offset;
1327 s32 ret_val; 1310 s32 ret_val = 0;
1328 u32 bank = 0; 1311 u32 bank = 0;
1329 u16 i, word; 1312 u16 i, word;
1330 1313
@@ -1339,12 +1322,15 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
1339 goto out; 1322 goto out;
1340 1323
1341 ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); 1324 ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
1342 if (ret_val) 1325 if (ret_val) {
1343 goto release; 1326 hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n");
1327 bank = 0;
1328 }
1344 1329
1345 act_offset = (bank) ? nvm->flash_bank_size : 0; 1330 act_offset = (bank) ? nvm->flash_bank_size : 0;
1346 act_offset += offset; 1331 act_offset += offset;
1347 1332
1333 ret_val = 0;
1348 for (i = 0; i < words; i++) { 1334 for (i = 0; i < words; i++) {
1349 if ((dev_spec->shadow_ram) && 1335 if ((dev_spec->shadow_ram) &&
1350 (dev_spec->shadow_ram[offset+i].modified)) { 1336 (dev_spec->shadow_ram[offset+i].modified)) {
@@ -1359,7 +1345,6 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
1359 } 1345 }
1360 } 1346 }
1361 1347
1362release:
1363 e1000_release_swflag_ich8lan(hw); 1348 e1000_release_swflag_ich8lan(hw);
1364 1349
1365out: 1350out:
@@ -1610,7 +1595,6 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
1610{ 1595{
1611 struct e1000_nvm_info *nvm = &hw->nvm; 1596 struct e1000_nvm_info *nvm = &hw->nvm;
1612 struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 1597 struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
1613 s32 ret_val;
1614 u16 i; 1598 u16 i;
1615 1599
1616 if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || 1600 if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
@@ -1619,17 +1603,11 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
1619 return -E1000_ERR_NVM; 1603 return -E1000_ERR_NVM;
1620 } 1604 }
1621 1605
1622 ret_val = e1000_acquire_swflag_ich8lan(hw);
1623 if (ret_val)
1624 return ret_val;
1625
1626 for (i = 0; i < words; i++) { 1606 for (i = 0; i < words; i++) {
1627 dev_spec->shadow_ram[offset+i].modified = 1; 1607 dev_spec->shadow_ram[offset+i].modified = 1;
1628 dev_spec->shadow_ram[offset+i].value = data[i]; 1608 dev_spec->shadow_ram[offset+i].value = data[i];
1629 } 1609 }
1630 1610
1631 e1000_release_swflag_ich8lan(hw);
1632
1633 return 0; 1611 return 0;
1634} 1612}
1635 1613
@@ -1670,8 +1648,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
1670 */ 1648 */
1671 ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); 1649 ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
1672 if (ret_val) { 1650 if (ret_val) {
1673 e1000_release_swflag_ich8lan(hw); 1651 hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n");
1674 goto out; 1652 bank = 0;
1675 } 1653 }
1676 1654
1677 if (bank == 0) { 1655 if (bank == 0) {
@@ -2057,12 +2035,8 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
2057 iteration = 1; 2035 iteration = 1;
2058 break; 2036 break;
2059 case 2: 2037 case 2:
2060 if (hw->mac.type == e1000_ich9lan) { 2038 sector_size = ICH_FLASH_SEG_SIZE_8K;
2061 sector_size = ICH_FLASH_SEG_SIZE_8K; 2039 iteration = 1;
2062 iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K;
2063 } else {
2064 return -E1000_ERR_NVM;
2065 }
2066 break; 2040 break;
2067 case 3: 2041 case 3:
2068 sector_size = ICH_FLASH_SEG_SIZE_64K; 2042 sector_size = ICH_FLASH_SEG_SIZE_64K;
@@ -2074,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
2074 2048
2075 /* Start with the base address, then add the sector offset. */ 2049 /* Start with the base address, then add the sector offset. */
2076 flash_linear_addr = hw->nvm.flash_base_addr; 2050 flash_linear_addr = hw->nvm.flash_base_addr;
2077 flash_linear_addr += (bank) ? (sector_size * iteration) : 0; 2051 flash_linear_addr += (bank) ? flash_bank_size : 0;
2078 2052
2079 for (j = 0; j < iteration ; j++) { 2053 for (j = 0; j < iteration ; j++) {
2080 do { 2054 do {