diff options
Diffstat (limited to 'drivers/net/e1000e/ich8lan.c')
| -rw-r--r-- | drivers/net/e1000e/ich8lan.c | 94 |
1 files changed, 43 insertions, 51 deletions
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index d56c7473144a..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 */ |
| @@ -594,8 +577,8 @@ static DEFINE_MUTEX(nvm_mutex); | |||
| 594 | **/ | 577 | **/ |
| 595 | static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) | 578 | static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) |
| 596 | { | 579 | { |
| 597 | u32 extcnf_ctrl; | 580 | u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; |
| 598 | u32 timeout = PHY_CFG_TIMEOUT; | 581 | s32 ret_val = 0; |
| 599 | 582 | ||
| 600 | might_sleep(); | 583 | might_sleep(); |
| 601 | 584 | ||
| @@ -603,28 +586,46 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) | |||
| 603 | 586 | ||
| 604 | while (timeout) { | 587 | while (timeout) { |
| 605 | extcnf_ctrl = er32(EXTCNF_CTRL); | 588 | extcnf_ctrl = er32(EXTCNF_CTRL); |
| 589 | if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) | ||
| 590 | break; | ||
| 606 | 591 | ||
| 607 | if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) { | 592 | mdelay(1); |
| 608 | extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; | 593 | timeout--; |
| 609 | ew32(EXTCNF_CTRL, extcnf_ctrl); | 594 | } |
| 595 | |||
| 596 | if (!timeout) { | ||
| 597 | hw_dbg(hw, "SW/FW/HW has locked the resource for too long.\n"); | ||
| 598 | ret_val = -E1000_ERR_CONFIG; | ||
| 599 | goto out; | ||
| 600 | } | ||
| 601 | |||
| 602 | timeout = PHY_CFG_TIMEOUT * 2; | ||
| 603 | |||
| 604 | extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; | ||
| 605 | ew32(EXTCNF_CTRL, extcnf_ctrl); | ||
| 606 | |||
| 607 | while (timeout) { | ||
| 608 | extcnf_ctrl = er32(EXTCNF_CTRL); | ||
| 609 | if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) | ||
| 610 | break; | ||
| 610 | 611 | ||
| 611 | extcnf_ctrl = er32(EXTCNF_CTRL); | ||
| 612 | if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) | ||
| 613 | break; | ||
| 614 | } | ||
| 615 | mdelay(1); | 612 | mdelay(1); |
| 616 | timeout--; | 613 | timeout--; |
| 617 | } | 614 | } |
| 618 | 615 | ||
| 619 | if (!timeout) { | 616 | if (!timeout) { |
| 620 | hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); | 617 | hw_dbg(hw, "Failed to acquire the semaphore.\n"); |
| 621 | extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; | 618 | extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; |
| 622 | ew32(EXTCNF_CTRL, extcnf_ctrl); | 619 | ew32(EXTCNF_CTRL, extcnf_ctrl); |
| 623 | mutex_unlock(&nvm_mutex); | 620 | ret_val = -E1000_ERR_CONFIG; |
| 624 | return -E1000_ERR_CONFIG; | 621 | goto out; |
| 625 | } | 622 | } |
| 626 | 623 | ||
| 627 | return 0; | 624 | out: |
| 625 | if (ret_val) | ||
| 626 | mutex_unlock(&nvm_mutex); | ||
| 627 | |||
| 628 | return ret_val; | ||
| 628 | } | 629 | } |
| 629 | 630 | ||
| 630 | /** | 631 | /** |
| @@ -1306,7 +1307,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, | |||
| 1306 | struct e1000_nvm_info *nvm = &hw->nvm; | 1307 | struct e1000_nvm_info *nvm = &hw->nvm; |
| 1307 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; | 1308 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; |
| 1308 | u32 act_offset; | 1309 | u32 act_offset; |
| 1309 | s32 ret_val; | 1310 | s32 ret_val = 0; |
| 1310 | u32 bank = 0; | 1311 | u32 bank = 0; |
| 1311 | u16 i, word; | 1312 | u16 i, word; |
| 1312 | 1313 | ||
| @@ -1321,12 +1322,15 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, | |||
| 1321 | goto out; | 1322 | goto out; |
| 1322 | 1323 | ||
| 1323 | ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); | 1324 | ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); |
| 1324 | if (ret_val) | 1325 | if (ret_val) { |
| 1325 | goto release; | 1326 | hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n"); |
| 1327 | bank = 0; | ||
| 1328 | } | ||
| 1326 | 1329 | ||
| 1327 | act_offset = (bank) ? nvm->flash_bank_size : 0; | 1330 | act_offset = (bank) ? nvm->flash_bank_size : 0; |
| 1328 | act_offset += offset; | 1331 | act_offset += offset; |
| 1329 | 1332 | ||
| 1333 | ret_val = 0; | ||
| 1330 | for (i = 0; i < words; i++) { | 1334 | for (i = 0; i < words; i++) { |
| 1331 | if ((dev_spec->shadow_ram) && | 1335 | if ((dev_spec->shadow_ram) && |
| 1332 | (dev_spec->shadow_ram[offset+i].modified)) { | 1336 | (dev_spec->shadow_ram[offset+i].modified)) { |
| @@ -1341,7 +1345,6 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, | |||
| 1341 | } | 1345 | } |
| 1342 | } | 1346 | } |
| 1343 | 1347 | ||
| 1344 | release: | ||
| 1345 | e1000_release_swflag_ich8lan(hw); | 1348 | e1000_release_swflag_ich8lan(hw); |
| 1346 | 1349 | ||
| 1347 | out: | 1350 | out: |
| @@ -1592,7 +1595,6 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, | |||
| 1592 | { | 1595 | { |
| 1593 | struct e1000_nvm_info *nvm = &hw->nvm; | 1596 | struct e1000_nvm_info *nvm = &hw->nvm; |
| 1594 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; | 1597 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; |
| 1595 | s32 ret_val; | ||
| 1596 | u16 i; | 1598 | u16 i; |
| 1597 | 1599 | ||
| 1598 | if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || | 1600 | if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || |
| @@ -1601,17 +1603,11 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, | |||
| 1601 | return -E1000_ERR_NVM; | 1603 | return -E1000_ERR_NVM; |
| 1602 | } | 1604 | } |
| 1603 | 1605 | ||
| 1604 | ret_val = e1000_acquire_swflag_ich8lan(hw); | ||
| 1605 | if (ret_val) | ||
| 1606 | return ret_val; | ||
| 1607 | |||
| 1608 | for (i = 0; i < words; i++) { | 1606 | for (i = 0; i < words; i++) { |
| 1609 | dev_spec->shadow_ram[offset+i].modified = 1; | 1607 | dev_spec->shadow_ram[offset+i].modified = 1; |
| 1610 | dev_spec->shadow_ram[offset+i].value = data[i]; | 1608 | dev_spec->shadow_ram[offset+i].value = data[i]; |
| 1611 | } | 1609 | } |
| 1612 | 1610 | ||
| 1613 | e1000_release_swflag_ich8lan(hw); | ||
| 1614 | |||
| 1615 | return 0; | 1611 | return 0; |
| 1616 | } | 1612 | } |
| 1617 | 1613 | ||
| @@ -1652,8 +1648,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) | |||
| 1652 | */ | 1648 | */ |
| 1653 | ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); | 1649 | ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); |
| 1654 | if (ret_val) { | 1650 | if (ret_val) { |
| 1655 | e1000_release_swflag_ich8lan(hw); | 1651 | hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n"); |
| 1656 | goto out; | 1652 | bank = 0; |
| 1657 | } | 1653 | } |
| 1658 | 1654 | ||
| 1659 | if (bank == 0) { | 1655 | if (bank == 0) { |
| @@ -2039,12 +2035,8 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) | |||
| 2039 | iteration = 1; | 2035 | iteration = 1; |
| 2040 | break; | 2036 | break; |
| 2041 | case 2: | 2037 | case 2: |
| 2042 | if (hw->mac.type == e1000_ich9lan) { | 2038 | sector_size = ICH_FLASH_SEG_SIZE_8K; |
| 2043 | sector_size = ICH_FLASH_SEG_SIZE_8K; | 2039 | iteration = 1; |
| 2044 | iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K; | ||
| 2045 | } else { | ||
| 2046 | return -E1000_ERR_NVM; | ||
| 2047 | } | ||
| 2048 | break; | 2040 | break; |
| 2049 | case 3: | 2041 | case 3: |
| 2050 | sector_size = ICH_FLASH_SEG_SIZE_64K; | 2042 | sector_size = ICH_FLASH_SEG_SIZE_64K; |
| @@ -2056,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) | |||
| 2056 | 2048 | ||
| 2057 | /* Start with the base address, then add the sector offset. */ | 2049 | /* Start with the base address, then add the sector offset. */ |
| 2058 | flash_linear_addr = hw->nvm.flash_base_addr; | 2050 | flash_linear_addr = hw->nvm.flash_base_addr; |
| 2059 | flash_linear_addr += (bank) ? (sector_size * iteration) : 0; | 2051 | flash_linear_addr += (bank) ? flash_bank_size : 0; |
| 2060 | 2052 | ||
| 2061 | for (j = 0; j < iteration ; j++) { | 2053 | for (j = 0; j < iteration ; j++) { |
| 2062 | do { | 2054 | do { |
