Commit 735c35af authored by Don Skidmore's avatar Don Skidmore Committed by Jeff Kirsher

ixgbe: cleanup checksum to allow error results

Currently the shared code checksum calculation function only
returns a u16 and cannot return an error code. Unfortunately
a variety of errors can happen that completely prevent the
calculation of a checksum. So, change the function return value
from a u16 to an s32 and return a negative value on error, or the
positive checksum value when there is no error.
Signed-off-by: default avatarDon Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 28abba05
...@@ -1625,7 +1625,7 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) ...@@ -1625,7 +1625,7 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
* ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
**/ **/
u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
{ {
u16 i; u16 i;
u16 j; u16 j;
...@@ -1636,7 +1636,7 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) ...@@ -1636,7 +1636,7 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
/* Include 0x0-0x3F in the checksum */ /* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
if (hw->eeprom.ops.read(hw, i, &word) != 0) { if (hw->eeprom.ops.read(hw, i, &word)) {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
break; break;
} }
...@@ -1645,24 +1645,35 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) ...@@ -1645,24 +1645,35 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
/* Include all data from pointers except for the fw pointer */ /* Include all data from pointers except for the fw pointer */
for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
hw->eeprom.ops.read(hw, i, &pointer); if (hw->eeprom.ops.read(hw, i, &pointer)) {
hw_dbg(hw, "EEPROM read failed\n");
return IXGBE_ERR_EEPROM;
}
/* If the pointer seems invalid */
if (pointer == 0xFFFF || pointer == 0)
continue;
if (hw->eeprom.ops.read(hw, pointer, &length)) {
hw_dbg(hw, "EEPROM read failed\n");
return IXGBE_ERR_EEPROM;
}
/* Make sure the pointer seems valid */ if (length == 0xFFFF || length == 0)
if (pointer != 0xFFFF && pointer != 0) { continue;
hw->eeprom.ops.read(hw, pointer, &length);
if (length != 0xFFFF && length != 0) { for (j = pointer + 1; j <= pointer + length; j++) {
for (j = pointer+1; j <= pointer+length; j++) { if (hw->eeprom.ops.read(hw, j, &word)) {
hw->eeprom.ops.read(hw, j, &word); hw_dbg(hw, "EEPROM read failed\n");
checksum += word; return IXGBE_ERR_EEPROM;
}
} }
checksum += word;
} }
} }
checksum = (u16)IXGBE_EEPROM_SUM - checksum; checksum = (u16)IXGBE_EEPROM_SUM - checksum;
return checksum; return (s32)checksum;
} }
/** /**
...@@ -1686,26 +1697,33 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, ...@@ -1686,26 +1697,33 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
* EEPROM read fails * EEPROM read fails
*/ */
status = hw->eeprom.ops.read(hw, 0, &checksum); status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status) {
hw_dbg(hw, "EEPROM read failed\n");
return status;
}
if (status == 0) { status = hw->eeprom.ops.calc_checksum(hw);
checksum = hw->eeprom.ops.calc_checksum(hw); if (status < 0)
return status;
hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); checksum = (u16)(status & 0xffff);
/* status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
* Verify read checksum from EEPROM is the same as if (status) {
* calculated checksum
*/
if (read_checksum != checksum)
status = IXGBE_ERR_EEPROM_CHECKSUM;
/* If the user cares, return the calculated checksum */
if (checksum_val)
*checksum_val = checksum;
} else {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
return status;
} }
/* Verify read checksum from EEPROM is the same as
* calculated checksum
*/
if (read_checksum != checksum)
status = IXGBE_ERR_EEPROM_CHECKSUM;
/* If the user cares, return the calculated checksum */
if (checksum_val)
*checksum_val = checksum;
return status; return status;
} }
...@@ -1724,15 +1742,19 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) ...@@ -1724,15 +1742,19 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
* EEPROM read fails * EEPROM read fails
*/ */
status = hw->eeprom.ops.read(hw, 0, &checksum); status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status) {
if (status == 0) {
checksum = hw->eeprom.ops.calc_checksum(hw);
status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
checksum);
} else {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
return status;
} }
status = hw->eeprom.ops.calc_checksum(hw);
if (status < 0)
return status;
checksum = (u16)(status & 0xffff);
status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum);
return status; return status;
} }
......
...@@ -64,7 +64,7 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, ...@@ -64,7 +64,7 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data); u16 *data);
s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data); u16 words, u16 *data);
u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 *checksum_val); u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
......
...@@ -2871,7 +2871,7 @@ struct ixgbe_eeprom_operations { ...@@ -2871,7 +2871,7 @@ struct ixgbe_eeprom_operations {
s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *);
s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
s32 (*update_checksum)(struct ixgbe_hw *); s32 (*update_checksum)(struct ixgbe_hw *);
u16 (*calc_checksum)(struct ixgbe_hw *); s32 (*calc_checksum)(struct ixgbe_hw *);
}; };
struct ixgbe_mac_operations { struct ixgbe_mac_operations {
......
...@@ -316,7 +316,7 @@ static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, ...@@ -316,7 +316,7 @@ static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
* *
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
**/ **/
static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) static s32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
{ {
u16 i; u16 i;
u16 j; u16 j;
...@@ -324,6 +324,8 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -324,6 +324,8 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
u16 length = 0; u16 length = 0;
u16 pointer = 0; u16 pointer = 0;
u16 word = 0; u16 word = 0;
u16 checksum_last_word = IXGBE_EEPROM_CHECKSUM;
u16 ptr_start = IXGBE_PCIE_ANALOG_PTR;
/* /*
* Do not use hw->eeprom.ops.read because we do not want to take * Do not use hw->eeprom.ops.read because we do not want to take
...@@ -332,10 +334,10 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -332,10 +334,10 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
*/ */
/* Include 0x0-0x3F in the checksum */ /* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { for (i = 0; i < checksum_last_word; i++) {
if (ixgbe_read_eerd_generic(hw, i, &word) != 0) { if (ixgbe_read_eerd_generic(hw, i, &word)) {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
break; return IXGBE_ERR_EEPROM;
} }
checksum += word; checksum += word;
} }
...@@ -344,11 +346,11 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -344,11 +346,11 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
* Include all data from pointers 0x3, 0x6-0xE. This excludes the * Include all data from pointers 0x3, 0x6-0xE. This excludes the
* FW, PHY module, and PCIe Expansion/Option ROM pointers. * FW, PHY module, and PCIe Expansion/Option ROM pointers.
*/ */
for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { for (i = ptr_start; i < IXGBE_FW_PTR; i++) {
if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
continue; continue;
if (ixgbe_read_eerd_generic(hw, i, &pointer) != 0) { if (ixgbe_read_eerd_generic(hw, i, &pointer)) {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
break; break;
} }
...@@ -358,8 +360,9 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -358,8 +360,9 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
pointer >= hw->eeprom.word_size) pointer >= hw->eeprom.word_size)
continue; continue;
if (ixgbe_read_eerd_generic(hw, pointer, &length) != 0) { if (ixgbe_read_eerd_generic(hw, pointer, &length)) {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
return IXGBE_ERR_EEPROM;
break; break;
} }
...@@ -368,10 +371,10 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -368,10 +371,10 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
(pointer + length) >= hw->eeprom.word_size) (pointer + length) >= hw->eeprom.word_size)
continue; continue;
for (j = pointer+1; j <= pointer+length; j++) { for (j = pointer + 1; j <= pointer + length; j++) {
if (ixgbe_read_eerd_generic(hw, j, &word) != 0) { if (ixgbe_read_eerd_generic(hw, j, &word)) {
hw_dbg(hw, "EEPROM read failed\n"); hw_dbg(hw, "EEPROM read failed\n");
break; return IXGBE_ERR_EEPROM;
} }
checksum += word; checksum += word;
} }
...@@ -379,7 +382,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -379,7 +382,7 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
checksum = (u16)IXGBE_EEPROM_SUM - checksum; checksum = (u16)IXGBE_EEPROM_SUM - checksum;
return checksum; return (s32)checksum;
} }
/** /**
...@@ -410,23 +413,34 @@ static s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, ...@@ -410,23 +413,34 @@ static s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)) if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
return IXGBE_ERR_SWFW_SYNC; return IXGBE_ERR_SWFW_SYNC;
checksum = hw->eeprom.ops.calc_checksum(hw); status = hw->eeprom.ops.calc_checksum(hw);
if (status < 0)
goto out;
checksum = (u16)(status & 0xffff);
/* Do not use hw->eeprom.ops.read because we do not want to take /* Do not use hw->eeprom.ops.read because we do not want to take
* the synchronization semaphores twice here. * the synchronization semaphores twice here.
*/ */
status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM, status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
&read_checksum); &read_checksum);
if (status)
goto out;
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); /* Verify read checksum from EEPROM is the same as
* calculated checksum
*/
if (read_checksum != checksum) {
hw_dbg(hw, "Invalid EEPROM checksum");
status = IXGBE_ERR_EEPROM_CHECKSUM;
}
/* If the user cares, return the calculated checksum */ /* If the user cares, return the calculated checksum */
if (checksum_val) if (checksum_val)
*checksum_val = checksum; *checksum_val = checksum;
/* Verify read and calculated checksums are the same */ out:
if (read_checksum != checksum) hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return IXGBE_ERR_EEPROM_CHECKSUM;
return status; return status;
} }
...@@ -457,15 +471,22 @@ static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) ...@@ -457,15 +471,22 @@ static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)) if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
return IXGBE_ERR_SWFW_SYNC; return IXGBE_ERR_SWFW_SYNC;
checksum = hw->eeprom.ops.calc_checksum(hw); status = hw->eeprom.ops.calc_checksum(hw);
if (status < 0)
goto out;
checksum = (u16)(status & 0xffff);
/* Do not use hw->eeprom.ops.write because we do not want to /* Do not use hw->eeprom.ops.write because we do not want to
* take the synchronization semaphores twice here. * take the synchronization semaphores twice here.
*/ */
status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum); status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
if (!status) if (status)
status = ixgbe_update_flash_X540(hw); goto out;
status = ixgbe_update_flash_X540(hw);
out:
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment