Skip to content

Commit

Permalink
ixgbe: cleanup checksum to allow error results
Browse files Browse the repository at this point in the history
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: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Don Skidmore authored and Jeff Kirsher committed Dec 5, 2014
1 parent 28abba0 commit 735c35a
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 53 deletions.
86 changes: 54 additions & 32 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1625,7 +1625,7 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
* ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
* @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 j;
Expand All @@ -1636,7 +1636,7 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)

/* Include 0x0-0x3F in the checksum */
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");
break;
}
Expand All @@ -1645,24 +1645,35 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)

/* Include all data from pointers except for the fw pointer */
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 (pointer != 0xFFFF && pointer != 0) {
hw->eeprom.ops.read(hw, pointer, &length);
if (length == 0xFFFF || length == 0)
continue;

if (length != 0xFFFF && length != 0) {
for (j = pointer+1; j <= pointer+length; j++) {
hw->eeprom.ops.read(hw, j, &word);
checksum += word;
}
for (j = pointer + 1; j <= pointer + length; j++) {
if (hw->eeprom.ops.read(hw, j, &word)) {
hw_dbg(hw, "EEPROM read failed\n");
return IXGBE_ERR_EEPROM;
}
checksum += word;
}
}

checksum = (u16)IXGBE_EEPROM_SUM - checksum;

return checksum;
return (s32)checksum;
}

/**
Expand All @@ -1686,26 +1697,33 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
* EEPROM read fails
*/
status = hw->eeprom.ops.read(hw, 0, &checksum);
if (status) {
hw_dbg(hw, "EEPROM read failed\n");
return status;
}

if (status == 0) {
checksum = hw->eeprom.ops.calc_checksum(hw);
status = 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);

/*
* 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;
} else {
status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
if (status) {
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;
}

Expand All @@ -1724,15 +1742,19 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
* EEPROM read fails
*/
status = hw->eeprom.ops.read(hw, 0, &checksum);

if (status == 0) {
checksum = hw->eeprom.ops.calc_checksum(hw);
status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
checksum);
} else {
if (status) {
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;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data);
s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
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,
u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2871,7 +2871,7 @@ struct ixgbe_eeprom_operations {
s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *);
s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
s32 (*update_checksum)(struct ixgbe_hw *);
u16 (*calc_checksum)(struct ixgbe_hw *);
s32 (*calc_checksum)(struct ixgbe_hw *);
};

struct ixgbe_mac_operations {
Expand Down
59 changes: 40 additions & 19 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,16 @@ static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
*
* @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 j;
u16 checksum = 0;
u16 length = 0;
u16 pointer = 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
Expand All @@ -332,10 +334,10 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
*/

/* Include 0x0-0x3F in the checksum */
for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
if (ixgbe_read_eerd_generic(hw, i, &word) != 0) {
for (i = 0; i < checksum_last_word; i++) {
if (ixgbe_read_eerd_generic(hw, i, &word)) {
hw_dbg(hw, "EEPROM read failed\n");
break;
return IXGBE_ERR_EEPROM;
}
checksum += word;
}
Expand All @@ -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
* 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)
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");
break;
}
Expand All @@ -358,8 +360,9 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
pointer >= hw->eeprom.word_size)
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");
return IXGBE_ERR_EEPROM;
break;
}

Expand All @@ -368,18 +371,18 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
(pointer + length) >= hw->eeprom.word_size)
continue;

for (j = pointer+1; j <= pointer+length; j++) {
if (ixgbe_read_eerd_generic(hw, j, &word) != 0) {
for (j = pointer + 1; j <= pointer + length; j++) {
if (ixgbe_read_eerd_generic(hw, j, &word)) {
hw_dbg(hw, "EEPROM read failed\n");
break;
return IXGBE_ERR_EEPROM;
}
checksum += word;
}
}

checksum = (u16)IXGBE_EEPROM_SUM - checksum;

return checksum;
return (s32)checksum;
}

/**
Expand Down Expand Up @@ -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))
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
* the synchronization semaphores twice here.
*/
status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_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 (checksum_val)
*checksum_val = checksum;

/* Verify read and calculated checksums are the same */
if (read_checksum != checksum)
return IXGBE_ERR_EEPROM_CHECKSUM;
out:
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);

return status;
}
Expand Down Expand Up @@ -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))
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
* take the synchronization semaphores twice here.
*/
status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
if (!status)
status = ixgbe_update_flash_X540(hw);
if (status)
goto out;

status = ixgbe_update_flash_X540(hw);

out:
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
Expand Down

0 comments on commit 735c35a

Please sign in to comment.