diff options
-rw-r--r-- | sys/dev/pci/ixgbe.c | 405 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_type.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_x540.c | 142 |
4 files changed, 356 insertions, 201 deletions
diff --git a/sys/dev/pci/ixgbe.c b/sys/dev/pci/ixgbe.c index 462c79e7458..23128bc744b 100644 --- a/sys/dev/pci/ixgbe.c +++ b/sys/dev/pci/ixgbe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe.c,v 1.17 2016/11/17 19:26:57 mikeb Exp $ */ +/* $OpenBSD: ixgbe.c,v 1.18 2016/11/17 20:44:04 mikeb Exp $ */ /****************************************************************************** @@ -895,27 +895,25 @@ int32_t ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) } /** - * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM + * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to - * @data: 16 bit word to be written to the EEPROM + * @words: number of word(s) + * @data: 16 bit word(s) to be written to the EEPROM * * If ixgbe_eeprom_update_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ -int32_t ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data) +static int32_t ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data) { int32_t status; + uint16_t word; + uint16_t page_size; + uint16_t i; uint8_t write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; - DEBUGFUNC("ixgbe_write_eeprom_generic"); - - hw->eeprom.ops.init_params(hw); - - if (offset >= hw->eeprom.word_size) { - status = IXGBE_ERR_EEPROM; - goto out; - } + DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); /* Prepare the EEPROM for writing */ status = ixgbe_acquire_eeprom(hw); @@ -928,54 +926,71 @@ int32_t ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_ } if (status == IXGBE_SUCCESS) { - ixgbe_standby_eeprom(hw); - - /* Send the WRITE ENABLE command (8 bit opcode ) */ - ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, - IXGBE_EEPROM_OPCODE_BITS); - - ixgbe_standby_eeprom(hw); - - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((hw->eeprom.address_bits == 8) && (offset >= 128)) - write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + for (i = 0; i < words; i++) { + ixgbe_standby_eeprom(hw); - /* Send the Write command (8-bit opcode + addr) */ - ixgbe_shift_out_eeprom_bits(hw, write_opcode, - IXGBE_EEPROM_OPCODE_BITS); - ixgbe_shift_out_eeprom_bits(hw, (uint16_t)(offset*2), - hw->eeprom.address_bits); + /* Send the WRITE ENABLE command (8 bit opcode ) */ + ixgbe_shift_out_eeprom_bits(hw, + IXGBE_EEPROM_WREN_OPCODE_SPI, + IXGBE_EEPROM_OPCODE_BITS); - /* Send the data */ - data = (data >> 8) | (data << 8); - ixgbe_shift_out_eeprom_bits(hw, data, 16); - ixgbe_standby_eeprom(hw); + ixgbe_standby_eeprom(hw); + /* + * Some SPI eeproms use the 8th address bit embedded + * in the opcode + */ + if ((hw->eeprom.address_bits == 8) && + ((offset + i) >= 128)) + write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + + /* Send the Write command (8-bit opcode + addr) */ + ixgbe_shift_out_eeprom_bits(hw, write_opcode, + IXGBE_EEPROM_OPCODE_BITS); + ixgbe_shift_out_eeprom_bits(hw, (uint16_t)((offset + i) * 2), + hw->eeprom.address_bits); + + page_size = hw->eeprom.word_page_size; + + /* Send the data in burst via SPI*/ + do { + word = data[i]; + word = (word >> 8) | (word << 8); + ixgbe_shift_out_eeprom_bits(hw, word, 16); + + if (page_size == 0) + break; + + /* do not wrap around page */ + if (((offset + i) & (page_size - 1)) == + (page_size - 1)) + break; + } while (++i < words); + + ixgbe_standby_eeprom(hw); + msec_delay(10); + } /* Done with writing - release the EEPROM */ ixgbe_release_eeprom(hw); } -out: return status; } /** - * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang + * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM * @hw: pointer to hardware structure - * @offset: offset within the EEPROM to be read - * @data: read 16 bit value from EEPROM + * @offset: offset within the EEPROM to be written to + * @data: 16 bit word to be written to the EEPROM * - * Reads 16 bit value from EEPROM through bit-bang method + * If ixgbe_eeprom_update_checksum is not called after this function, the + * EEPROM will most likely contain an invalid checksum. **/ -int32_t ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, uint16_t offset, - uint16_t *data) +int32_t ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data) { int32_t status; - uint16_t word_in; - uint8_t read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + + DEBUGFUNC("ixgbe_write_eeprom_generic"); hw->eeprom.ops.init_params(hw); @@ -984,6 +999,31 @@ int32_t ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, uint16_t offset, goto out; } + status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); + +out: + return status; +} + +/** + * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be read + * @words: number of word(s) + * @data: read 16 bit word(s) from EEPROM + * + * Reads 16 bit word(s) from EEPROM through bit-bang method + **/ +static int32_t ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data) +{ + int32_t status; + uint16_t word_in; + uint8_t read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + uint16_t i; + + DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); + /* Prepare the EEPROM for reading */ status = ixgbe_acquire_eeprom(hw); @@ -995,104 +1035,176 @@ int32_t ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, uint16_t offset, } if (status == IXGBE_SUCCESS) { - ixgbe_standby_eeprom(hw); + for (i = 0; i < words; i++) { + ixgbe_standby_eeprom(hw); + /* + * Some SPI eeproms use the 8th address bit embedded + * in the opcode + */ + if ((hw->eeprom.address_bits == 8) && + ((offset + i) >= 128)) + read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + + /* Send the READ command (opcode + addr) */ + ixgbe_shift_out_eeprom_bits(hw, read_opcode, + IXGBE_EEPROM_OPCODE_BITS); + ixgbe_shift_out_eeprom_bits(hw, (uint16_t)((offset + i) * 2), + hw->eeprom.address_bits); + + /* Read the data. */ + word_in = ixgbe_shift_in_eeprom_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((hw->eeprom.address_bits == 8) && (offset >= 128)) - read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; + /* End this read operation */ + ixgbe_release_eeprom(hw); + } - /* Send the READ command (opcode + addr) */ - ixgbe_shift_out_eeprom_bits(hw, read_opcode, - IXGBE_EEPROM_OPCODE_BITS); - ixgbe_shift_out_eeprom_bits(hw, (uint16_t)(offset*2), - hw->eeprom.address_bits); + return status; +} - /* Read the data. */ - word_in = ixgbe_shift_in_eeprom_bits(hw, 16); - *data = (word_in >> 8) | (word_in << 8); +/** + * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang + * @hw: pointer to hardware structure + * @offset: offset within the EEPROM to be read + * @data: read 16 bit value from EEPROM + * + * Reads 16 bit value from EEPROM through bit-bang method + **/ +int32_t ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, uint16_t offset, + uint16_t *data) +{ + int32_t status; - /* End this read operation */ - ixgbe_release_eeprom(hw); + DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); + + hw->eeprom.ops.init_params(hw); + + if (offset >= hw->eeprom.word_size) { + status = IXGBE_ERR_EEPROM; + goto out; } + status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); + out: return status; } /** - * ixgbe_read_eerd_generic - Read EEPROM word using EERD + * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to read - * @data: word read from the EEPROM + * @offset: offset of word in the EEPROM to read + * @words: number of word(s) + * @data: 16 bit word(s) from the EEPROM * - * Reads a 16 bit word from the EEPROM using the EERD register. + * Reads a 16 bit word(s) from the EEPROM using the EERD register. **/ -int32_t ixgbe_read_eerd_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data) +int32_t ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data) { uint32_t eerd; - int32_t status; + int32_t status = IXGBE_SUCCESS; + uint32_t i; + + DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); hw->eeprom.ops.init_params(hw); + if (words == 0) { + status = IXGBE_ERR_INVALID_ARGUMENT; + ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); + goto out; + } + if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; + ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); goto out; } - eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) + - IXGBE_EEPROM_RW_REG_START; + for (i = 0; i < words; i++) { + eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | + IXGBE_EEPROM_RW_REG_START; - IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); - - if (status == IXGBE_SUCCESS) - *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> - IXGBE_EEPROM_RW_REG_DATA); - else - DEBUGOUT("Eeprom read timed out\n"); + IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); + if (status == IXGBE_SUCCESS) { + data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> + IXGBE_EEPROM_RW_REG_DATA); + } else { + DEBUGOUT("Eeprom read timed out\n"); + goto out; + } + } out: return status; } /** - * ixgbe_write_eewr_generic - Write EEPROM word using EEWR + * ixgbe_read_eerd_generic - Read EEPROM word using EERD + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM using the EERD register. + **/ +int32_t ixgbe_read_eerd_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data) +{ + return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); +} + +/** + * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write - * @data: word write to the EEPROM + * @words: number of word(s) + * @data: word(s) write to the EEPROM * - * Write a 16 bit word to the EEPROM using the EEWR register. + * Write a 16 bit word(s) to the EEPROM using the EEWR register. **/ -int32_t ixgbe_write_eewr_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data) +int32_t ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data) { uint32_t eewr; - int32_t status; + int32_t status = IXGBE_SUCCESS; + uint16_t i; + + DEBUGFUNC("ixgbe_write_eewr_generic"); hw->eeprom.ops.init_params(hw); + if (words == 0) { + status = IXGBE_ERR_INVALID_ARGUMENT; + ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); + goto out; + } + if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; + ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); goto out; } - eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) | - (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START; + for (i = 0; i < words; i++) { + eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | + (data[i] << IXGBE_EEPROM_RW_REG_DATA) | + IXGBE_EEPROM_RW_REG_START; - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); - if (status != IXGBE_SUCCESS) { - DEBUGOUT("Eeprom write EEWR timed out\n"); - goto out; - } + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != IXGBE_SUCCESS) { + DEBUGOUT("Eeprom write EEWR timed out\n"); + goto out; + } - IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); + IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); - status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); - if (status != IXGBE_SUCCESS) { - DEBUGOUT("Eeprom write EEWR timed out\n"); - goto out; + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); + if (status != IXGBE_SUCCESS) { + DEBUGOUT("Eeprom write EEWR timed out\n"); + goto out; + } } out: @@ -1100,6 +1212,19 @@ out: } /** + * ixgbe_write_eewr_generic - Write EEPROM word using EEWR + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @data: word write to the EEPROM + * + * Write a 16 bit word to the EEPROM using the EEWR register. + **/ +int32_t ixgbe_write_eewr_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data) +{ + return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); +} + +/** * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure * @ee_reg: EEPROM flag for polling @@ -1372,7 +1497,7 @@ void ixgbe_standby_eeprom(struct ixgbe_hw *hw) * @count: number of bits to shift out **/ void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, uint16_t data, - uint16_t count) + uint16_t count) { uint32_t eec; uint32_t mask; @@ -1532,8 +1657,10 @@ void ixgbe_release_eeprom(struct ixgbe_hw *hw) /** * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum * @hw: pointer to hardware structure + * + * Returns a negative error code on error, or the 16-bit checksum **/ -uint16_t ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) +int32_t ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) { uint16_t i; uint16_t j; @@ -1546,33 +1673,44 @@ uint16_t 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) != IXGBE_SUCCESS) { + if (hw->eeprom.ops.read(hw, i, &word)) { DEBUGOUT("EEPROM read failed\n"); - break; + return IXGBE_ERR_EEPROM; } checksum += word; } /* 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)) { + DEBUGOUT("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 the pointer seems invalid */ + if (pointer == 0xFFFF || pointer == 0) + continue; - if (length != 0xFFFF && length != 0) { - for (j = pointer+1; j <= pointer+length; j++) { - hw->eeprom.ops.read(hw, j, &word); - checksum += word; - } + if (hw->eeprom.ops.read(hw, pointer, &length)) { + DEBUGOUT("EEPROM read failed\n"); + return IXGBE_ERR_EEPROM; + } + + if (length == 0xFFFF || length == 0) + continue; + + for (j = pointer + 1; j <= pointer + length; j++) { + if (hw->eeprom.ops.read(hw, j, &word)) { + DEBUGOUT("EEPROM read failed\n"); + return IXGBE_ERR_EEPROM; } + checksum += word; } } checksum = (uint16_t)IXGBE_EEPROM_SUM - checksum; - return checksum; + return (int32_t)checksum; } /** @@ -1597,26 +1735,33 @@ int32_t ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); + if (status) { + DEBUGOUT("EEPROM read failed\n"); + return status; + } - if (status == IXGBE_SUCCESS) { - checksum = hw->eeprom.ops.calc_checksum(hw); - - hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); + status = hw->eeprom.ops.calc_checksum(hw); + if (status < 0) + return status; - /* - * Verify read checksum from EEPROM is the same as - * calculated checksum - */ - if (read_checksum != checksum) - status = IXGBE_ERR_EEPROM_CHECKSUM; + checksum = (uint16_t)(status & 0xffff); - /* 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) { DEBUGOUT("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; } @@ -1636,15 +1781,19 @@ int32_t ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); - - if (status == IXGBE_SUCCESS) { - checksum = hw->eeprom.ops.calc_checksum(hw); - status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, - checksum); - } else { + if (status) { DEBUGOUT("EEPROM read failed\n"); + return status; } + status = hw->eeprom.ops.calc_checksum(hw); + if (status < 0) + return status; + + checksum = (uint16_t)(status & 0xffff); + + status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); + return status; } diff --git a/sys/dev/pci/ixgbe.h b/sys/dev/pci/ixgbe.h index abef797ceea..959e368d349 100644 --- a/sys/dev/pci/ixgbe.h +++ b/sys/dev/pci/ixgbe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe.h,v 1.24 2016/11/17 19:26:57 mikeb Exp $ */ +/* $OpenBSD: ixgbe.h,v 1.25 2016/11/17 20:44:04 mikeb Exp $ */ /****************************************************************************** @@ -176,7 +176,7 @@ int32_t ixgbe_read_eerd_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t * int32_t ixgbe_write_eewr_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t data); int32_t ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data); -uint16_t ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); +int32_t ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); int32_t ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, uint16_t *checksum_val); int32_t ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); @@ -340,7 +340,6 @@ int32_t ixgbe_check_for_msg(struct ixgbe_hw *, uint16_t); int32_t ixgbe_check_for_ack(struct ixgbe_hw *, uint16_t); int32_t ixgbe_check_for_rst(struct ixgbe_hw *, uint16_t); void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw); -void ixgbe_init_mbx_params_vf(struct ixgbe_hw *); void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); #endif /* _IXGBE_H_ */ diff --git a/sys/dev/pci/ixgbe_type.h b/sys/dev/pci/ixgbe_type.h index 47eb87c6aaf..ba8f578609f 100644 --- a/sys/dev/pci/ixgbe_type.h +++ b/sys/dev/pci/ixgbe_type.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe_type.h,v 1.26 2016/11/17 19:26:57 mikeb Exp $ */ +/* $OpenBSD: ixgbe_type.h,v 1.27 2016/11/17 20:44:04 mikeb Exp $ */ /****************************************************************************** @@ -3386,7 +3386,7 @@ struct ixgbe_eeprom_operations { int32_t (*write)(struct ixgbe_hw *, uint16_t, uint16_t); int32_t (*validate_checksum)(struct ixgbe_hw *, uint16_t *); int32_t (*update_checksum)(struct ixgbe_hw *); - uint16_t (*calc_checksum)(struct ixgbe_hw *); + int32_t (*calc_checksum)(struct ixgbe_hw *); }; struct ixgbe_mac_operations { @@ -3676,7 +3676,6 @@ struct ixgbe_hw { bool adapter_stopped; int api_version; bool force_full_reset; - bool mng_fw_enabled; }; /* Error Codes */ diff --git a/sys/dev/pci/ixgbe_x540.c b/sys/dev/pci/ixgbe_x540.c index 511d7bf7345..dcb7a2d1561 100644 --- a/sys/dev/pci/ixgbe_x540.c +++ b/sys/dev/pci/ixgbe_x540.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ixgbe_x540.c,v 1.7 2016/11/17 19:26:57 mikeb Exp $ */ +/* $OpenBSD: ixgbe_x540.c,v 1.8 2016/11/17 20:44:04 mikeb Exp $ */ /****************************************************************************** - Copyright (c) 2001-2013, Intel Corporation + Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/* FreeBSD: src/sys/dev/ixgbe/ixgbe_x540.c 251964 Jun 18 21:28:19 2013 UTC */ +/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x540.c 295093 2016-01-31 15:14:23Z smh $*/ #include <dev/pci/ixgbe.h> #include <dev/pci/ixgbe_type.h> @@ -61,7 +61,7 @@ int32_t ixgbe_read_eerd_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t *dat int32_t ixgbe_write_eewr_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t data); int32_t ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw); int32_t ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, uint16_t *checksum_val); -uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw); +int32_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw); int32_t ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, uint16_t mask); void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, uint16_t mask); @@ -378,18 +378,20 @@ int32_t ixgbe_write_eewr_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t dat * be used internally by function which utilize ixgbe_acquire_swfw_sync_X540. * * @hw: pointer to hardware structure + * + * Returns a negative error code on error, or the 16-bit checksum **/ -uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) +int32_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) { - uint16_t i; - uint16_t j; + uint16_t i, j; uint16_t checksum = 0; uint16_t length = 0; uint16_t pointer = 0; uint16_t word = 0; + uint16_t checksum_last_word = IXGBE_EEPROM_CHECKSUM; + uint16_t 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 * the synchronization semaphores here. Instead use * ixgbe_read_eerd_generic */ @@ -397,25 +399,25 @@ uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540"); /* Include 0x0-0x3F in the checksum */ - for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { - if (ixgbe_read_eerd_generic(hw, i, &word) != IXGBE_SUCCESS) { + for (i = 0; i <= checksum_last_word; i++) { + if (ixgbe_read_eerd_generic(hw, i, &word)) { DEBUGOUT("EEPROM read failed\n"); - break; + return IXGBE_ERR_EEPROM; } - checksum += word; + if (i != IXGBE_EEPROM_CHECKSUM) + checksum += word; } - /* - * 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. */ - 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) != IXGBE_SUCCESS) { + if (ixgbe_read_eerd_generic(hw, i, &pointer)) { DEBUGOUT("EEPROM read failed\n"); - break; + return IXGBE_ERR_EEPROM; } /* Skip pointer section if the pointer is invalid. */ @@ -423,10 +425,9 @@ uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) pointer >= hw->eeprom.word_size) continue; - if (ixgbe_read_eerd_generic(hw, pointer, &length) != - IXGBE_SUCCESS) { + if (ixgbe_read_eerd_generic(hw, pointer, &length)) { DEBUGOUT("EEPROM read failed\n"); - break; + return IXGBE_ERR_EEPROM; } /* Skip pointer section if length is invalid. */ @@ -434,11 +435,10 @@ uint16_t 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) != - IXGBE_SUCCESS) { + for (j = pointer + 1; j <= pointer + length; j++) { + if (ixgbe_read_eerd_generic(hw, j, &word)) { DEBUGOUT("EEPROM read failed\n"); - break; + return IXGBE_ERR_EEPROM; } checksum += word; } @@ -446,7 +446,7 @@ uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) checksum = (uint16_t)IXGBE_EEPROM_SUM - checksum; - return checksum; + return (int32_t)checksum; } /** @@ -471,39 +471,43 @@ int32_t ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); - - if (status != IXGBE_SUCCESS) { + if (status) { DEBUGOUT("EEPROM read failed\n"); - goto out; + return status; } - if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == - IXGBE_SUCCESS) { - checksum = hw->eeprom.ops.calc_checksum(hw); + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)) + return IXGBE_ERR_SWFW_SYNC; - /* - * Do not use hw->eeprom.ops.read because we do not want to take - * the synchronization semaphores twice here. - */ - ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM, - &read_checksum); + status = hw->eeprom.ops.calc_checksum(hw); + if (status < 0) + goto out; - /* - * Verify read checksum from EEPROM is the same as - * calculated checksum - */ - if (read_checksum != checksum) - status = IXGBE_ERR_EEPROM_CHECKSUM; + checksum = (uint16_t)(status & 0xffff); - /* If the user cares, return the calculated checksum */ - if (checksum_val) - *checksum_val = checksum; - hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); - } else { - status = IXGBE_ERR_SWFW_SYNC; + /* 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; + + /* Verify read checksum from EEPROM is the same as + * calculated checksum + */ + if (read_checksum != checksum) { + DEBUGOUT("Invalid EEPROM checksum\n"); + status = IXGBE_ERR_EEPROM_CHECKSUM; } + /* If the user cares, return the calculated checksum */ + if (checksum_val) + *checksum_val = checksum; + out: + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + return status; } @@ -527,27 +531,31 @@ int32_t ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); - - if (status != IXGBE_SUCCESS) + if (status) { DEBUGOUT("EEPROM read failed\n"); + return status; + } - if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == - IXGBE_SUCCESS) { - checksum = hw->eeprom.ops.calc_checksum(hw); + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)) + return IXGBE_ERR_SWFW_SYNC; - /* - * 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); + status = hw->eeprom.ops.calc_checksum(hw); + if (status < 0) + goto out; - if (status == IXGBE_SUCCESS) - status = ixgbe_update_flash_X540(hw); - hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); - } else { - status = IXGBE_ERR_SWFW_SYNC; - } + checksum = (uint16_t)(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) + goto out; + + status = ixgbe_update_flash_X540(hw); + +out: + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } |