Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+54 −32
Original line number Original line Diff line number Diff line
@@ -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)


	/* 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)


	/* 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;
		}


		/* Make sure the pointer seems valid */
		/* If the pointer seems invalid */
		if (pointer != 0xFFFF && pointer != 0) {
		if (pointer == 0xFFFF || pointer == 0)
			hw->eeprom.ops.read(hw, pointer, &length);
			continue;


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

		if (length == 0xFFFF || length == 0)
			continue;

		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;
	checksum = (u16)IXGBE_EEPROM_SUM - checksum;


	return checksum;
	return (s32)checksum;
}
}


/**
/**
@@ -1686,14 +1697,24 @@ 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) {
		hw_dbg(hw, "EEPROM read failed\n");
		return status;
	}

	/* Verify read checksum from EEPROM is the same as
	 * calculated checksum
	 * calculated checksum
	 */
	 */
	if (read_checksum != checksum)
	if (read_checksum != checksum)
@@ -1702,9 +1723,6 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
	/* 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;
	} else {
		hw_dbg(hw, "EEPROM read failed\n");
	}


	return status;
	return status;
}
}
@@ -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;
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -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);
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 {
+40 −19
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	 */
	 */


	/* 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)
	 * 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)
		    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;
		}
		}


@@ -369,9 +372,9 @@ static u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
			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)


	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,
	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)
	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)
		goto out;

	status = ixgbe_update_flash_X540(hw);
	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;
}
}