[go: nahoru, domu]

156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/*******************************************************************************
256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * Intel Ethernet Controller XL710 Family Linux Driver
4dc641b7319f19a17639ed7d36aaddbf090206644Greg Rose * Copyright(c) 2013 - 2014 Intel Corporation.
556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * This program is free software; you can redistribute it and/or modify it
756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * under the terms and conditions of the GNU General Public License,
856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * version 2, as published by the Free Software Foundation.
956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
1056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * This program is distributed in the hope it will be useful, but WITHOUT
1156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * more details.
1456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
15dc641b7319f19a17639ed7d36aaddbf090206644Greg Rose * You should have received a copy of the GNU General Public License along
16dc641b7319f19a17639ed7d36aaddbf090206644Greg Rose * with this program.  If not, see <http://www.gnu.org/licenses/>.
1756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
1856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * The full GNU General Public License is included in this distribution in
1956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * the file called "COPYING".
2056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
2156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * Contact Information:
2256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
2356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
2456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
2556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg ******************************************************************************/
2656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
2756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg#include "i40e_prototype.h"
2856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
2956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
303e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_init_nvm_ops - Initialize NVM function pointers
313e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to the HW structure
3256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
333e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * Setup the function pointers and the NVM info structure. Should be called
343e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * once per NVM initialization, e.g. inside the i40e_init_shared_code().
353e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * Please notice that the NVM term is used here (& in all methods covered
363e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * in this file) as an equivalent of the FLASH part mapped into the SR.
373e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * We are accessing FLASH always thru the Shadow RAM.
3856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
3956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_status i40e_init_nvm(struct i40e_hw *hw)
4056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
4156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	struct i40e_nvm_info *nvm = &hw->nvm;
4256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = 0;
4356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u32 fla, gens;
4456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u8 sr_size;
4556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
4656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* The SR size is stored regardless of the nvm programming mode
4756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 * as the blank mode may be used in the factory line.
4856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 */
4956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	gens = rd32(hw, I40E_GLNVM_GENS);
5056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
5156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			   I40E_GLNVM_GENS_SR_SIZE_SHIFT);
523e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Switching to words (sr_size contains power of 2KB) */
5356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
5456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
553e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Check if we are in the normal or blank NVM programming mode */
5656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	fla = rd32(hw, I40E_GLNVM_FLA);
573e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
583e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson		/* Max NVM timeout */
5956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		nvm->timeout = I40E_MAX_NVM_TIMEOUT;
6056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		nvm->blank_nvm_mode = false;
613e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	} else { /* Blank programming mode */
6256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		nvm->blank_nvm_mode = true;
6356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		ret_code = I40E_ERR_NVM_BLANK_MODE;
6456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		hw_dbg(hw, "NVM init error: unsupported blank mode.\n");
6556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
6656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
6756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
6856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
6956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
7056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
713e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_acquire_nvm - Generic request for acquiring the NVM ownership
723e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to the HW structure
733e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @access: NVM access type (read or write)
7456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
753e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * This function will request NVM ownership for reading
763e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * via the proper Admin Command.
7756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
7856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_status i40e_acquire_nvm(struct i40e_hw *hw,
7956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				       enum i40e_aq_resource_access_type access)
8056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
8156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = 0;
8256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u64 gtime, timeout;
8356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u64 time = 0;
8456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
8556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (hw->nvm.blank_nvm_mode)
8656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		goto i40e_i40e_acquire_nvm_exit;
8756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
8856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
8956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg					    0, &time, NULL);
903e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Reading the Global Device Timer */
9156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	gtime = rd32(hw, I40E_GLVFGEN_TIMER);
9256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
933e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Store the timeout */
9456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
9556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
9656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (ret_code) {
973e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson		/* Set the polling timeout */
9856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (time > I40E_MAX_NVM_TIMEOUT)
9956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT)
10056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				  + gtime;
10156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		else
10256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			timeout = hw->nvm.hw_semaphore_timeout;
1033e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson		/* Poll until the current NVM owner timeouts */
10456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		while (gtime < timeout) {
10556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			usleep_range(10000, 20000);
10656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			ret_code = i40e_aq_request_resource(hw,
10756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg							I40E_NVM_RESOURCE_ID,
10856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg							access, 0, &time,
10956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg							NULL);
11056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			if (!ret_code) {
11156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				hw->nvm.hw_semaphore_timeout =
11256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg						I40E_MS_TO_GTIME(time) + gtime;
11356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				break;
11456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			}
11556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			gtime = rd32(hw, I40E_GLVFGEN_TIMER);
11656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
11756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (ret_code) {
11856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			hw->nvm.hw_semaphore_timeout = 0;
11956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			hw->nvm.hw_semaphore_wait =
12056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg						I40E_MS_TO_GTIME(time) + gtime;
12156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			hw_dbg(hw, "NVM acquire timed out, wait %llu ms before trying again.\n",
12256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				  time);
12356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
12456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
12556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
12656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_i40e_acquire_nvm_exit:
12756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
12856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
12956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
13056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
1313e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_release_nvm - Generic request for releasing the NVM ownership
1323e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to the HW structure
13356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
1343e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * This function will release NVM resource via the proper Admin Command.
13556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
13656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgvoid i40e_release_nvm(struct i40e_hw *hw)
13756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
13856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (!hw->nvm.blank_nvm_mode)
13956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
14056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
14156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
14256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
1433e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
1443e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to the HW structure
14556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
1463e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * Polls the SRCTL Shadow RAM register done bit.
14756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
14856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgstatic i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
14956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
15056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = I40E_ERR_TIMEOUT;
15156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u32 srctl, wait_cnt;
15256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
1533e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Poll the I40E_GLNVM_SRCTL until the done bit is set */
15456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
15556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		srctl = rd32(hw, I40E_GLNVM_SRCTL);
15656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
15756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			ret_code = 0;
15856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			break;
15956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
16056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		udelay(5);
16156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
16256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (ret_code == I40E_ERR_TIMEOUT)
163c5ffe7e1f745984b37b8ffe03b03f3d716a072f3Jakub Kicinski		hw_dbg(hw, "Done bit in GLNVM_SRCTL not set\n");
16456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
16556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
16656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
16756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
1683e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_read_nvm_word - Reads Shadow RAM
1693e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to the HW structure
1703e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
1713e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @data: word read from the Shadow RAM
17256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
1733e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
17456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
175a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelsoni40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
176a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson					 u16 *data)
17756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
17856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = I40E_ERR_TIMEOUT;
17956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u32 sr_reg;
18056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
18156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (offset >= hw->nvm.sr_size) {
18256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		hw_dbg(hw, "NVM read error: Offset beyond Shadow RAM limit.\n");
18356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		ret_code = I40E_ERR_PARAM;
18456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		goto read_nvm_exit;
18556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
18656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
1873e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Poll the done bit first */
18856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	ret_code = i40e_poll_sr_srctl_done_bit(hw);
18956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (!ret_code) {
1903e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson		/* Write the address and start reading */
19156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
19256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			 (1 << I40E_GLNVM_SRCTL_START_SHIFT);
19356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
19456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
1953e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson		/* Poll I40E_GLNVM_SRCTL until the done bit is set */
19656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		ret_code = i40e_poll_sr_srctl_done_bit(hw);
19756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (!ret_code) {
19856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
19956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			*data = (u16)((sr_reg &
20056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				       I40E_GLNVM_SRDATA_RDDATA_MASK)
20156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				    >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
20256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
20356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
20456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (ret_code)
20556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		hw_dbg(hw, "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
20656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			  offset);
20756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
20856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgread_nvm_exit:
20956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
21056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
21156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
21256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
2133e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_read_nvm_buffer - Reads Shadow RAM buffer
2143e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to the HW structure
2153e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
2163e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @words: (in) number of words to read; (out) number of words actually read
2173e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @data: words read from the Shadow RAM
21856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
2193e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
2203e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * method. The buffer read is preceded by the NVM ownership take
2213e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * and followed by the release.
22256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
22356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
22456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg					   u16 *words, u16 *data)
22556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
22656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = 0;
22756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u16 index, word;
22856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
2293e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Loop thru the selected region */
230a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson	for (word = 0; word < *words; word++) {
231a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson		index = offset + word;
232a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson		ret_code = i40e_read_nvm_word(hw, index, &data[word]);
233a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson		if (ret_code)
234a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson			break;
23556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
23656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
2373e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson	/* Update the number of words read from the Shadow RAM */
238a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson	*words = word;
239a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson
24056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
24156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
24256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
24356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
244cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_write_nvm_aq - Writes Shadow RAM.
245cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to the HW structure.
246cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @module_pointer: module pointer location in words from the NVM beginning
247cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @offset: offset in words from module start
248cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @words: number of words to write
249cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @data: buffer with words to write to the Shadow RAM
250cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @last_command: tells the AdminQ that this is the last command
251cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
252cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
253cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
254952d9639dba84e2a979cf4dd8edab3542b477ba3Wei Yongjunstatic i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
255952d9639dba84e2a979cf4dd8edab3542b477ba3Wei Yongjun				     u32 offset, u16 words, void *data,
256952d9639dba84e2a979cf4dd8edab3542b477ba3Wei Yongjun				     bool last_command)
257cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
258cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status ret_code = I40E_ERR_NVM;
259cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
260cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	/* Here we are checking the SR limit only for the flat memory model.
261cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	 * We cannot do it for the module-based model, as we did not acquire
262cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	 * the NVM resource yet (we cannot get the module pointer value).
263cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	 * Firmware will check the module-based model.
264cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	 */
265cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if ((offset + words) > hw->nvm.sr_size)
266cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		hw_dbg(hw, "NVM write error: offset beyond Shadow RAM limit.\n");
267cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
268cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		/* We can write only up to 4KB (one sector), in one AQ write */
269cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		hw_dbg(hw, "NVM write fail error: cannot write more than 4KB in a single write.\n");
270cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
271cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
272cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		/* A single write cannot spread over two sectors */
273cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		hw_dbg(hw, "NVM write error: cannot spread over two sectors in a single write.\n");
274cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	else
275cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		ret_code = i40e_aq_update_nvm(hw, module_pointer,
276cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					      2 * offset,  /*bytes*/
277cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					      2 * words,   /*bytes*/
278cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					      data, last_command, NULL);
279cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
280cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return ret_code;
281cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
282cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
283cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
2843e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_calc_nvm_checksum - Calculates and returns the checksum
2853e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to hardware structure
2863e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @checksum: pointer to the checksum
28756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
2883e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * This function calculates SW Checksum that covers the whole 64kB shadow RAM
2893e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
2903e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * is customer specific and unknown. Therefore, this function skips all maximum
2913e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * possible size of VPD (1kB).
29256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
29356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgstatic i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
29456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg						    u16 *checksum)
29556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
29656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = 0;
29756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u16 pcie_alt_module = 0;
29856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u16 checksum_local = 0;
29956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u16 vpd_module = 0;
30056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u16 word = 0;
30156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u32 i = 0;
30256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
30356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* read pointer to VPD area */
304a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson	ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
30556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (ret_code) {
30656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		ret_code = I40E_ERR_NVM_CHECKSUM;
30756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		goto i40e_calc_nvm_checksum_exit;
30856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
30956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
31056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* read pointer to PCIe Alt Auto-load module */
311a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson	ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
31256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				       &pcie_alt_module);
31356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (ret_code) {
31456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		ret_code = I40E_ERR_NVM_CHECKSUM;
31556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		goto i40e_calc_nvm_checksum_exit;
31656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
31756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
31856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* Calculate SW checksum that covers the whole 64kB shadow RAM
31956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 * except the VPD and PCIe ALT Auto-load modules
32056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 */
32156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	for (i = 0; i < hw->nvm.sr_size; i++) {
32256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		/* Skip Checksum word */
32356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (i == I40E_SR_SW_CHECKSUM_WORD)
32456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			i++;
32556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		/* Skip VPD module (convert byte size to word count) */
32656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (i == (u32)vpd_module) {
32756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2);
32856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			if (i >= hw->nvm.sr_size)
32956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				break;
33056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
33156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		/* Skip PCIe ALT module (convert byte size to word count) */
33256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (i == (u32)pcie_alt_module) {
33356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2);
33456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			if (i >= hw->nvm.sr_size)
33556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg				break;
33656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
33756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
338a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson		ret_code = i40e_read_nvm_word(hw, (u16)i, &word);
33956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		if (ret_code) {
34056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			ret_code = I40E_ERR_NVM_CHECKSUM;
34156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg			goto i40e_calc_nvm_checksum_exit;
34256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		}
34356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		checksum_local += word;
34456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	}
34556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
34656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	*checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
34756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
34856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_calc_nvm_checksum_exit:
34956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
35056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
35156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
35256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg/**
353cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_update_nvm_checksum - Updates the NVM checksum
354cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
355cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
356cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * NVM ownership must be acquired before calling this function and released
357cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * on ARQ completion event reception by caller.
358cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * This function will commit SR to NVM.
359cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
360cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsoni40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
361cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
362cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status ret_code = 0;
363cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	u16 checksum;
364cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
365cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	ret_code = i40e_calc_nvm_checksum(hw, &checksum);
366cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if (!ret_code)
367cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
368cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     1, &checksum, true);
369cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
370cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return ret_code;
371cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
372cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
373cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
3743e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * i40e_validate_nvm_checksum - Validate EEPROM checksum
3753e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @hw: pointer to hardware structure
3763e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * @checksum: calculated checksum
37756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg *
3783e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * Performs checksum calculation and validates the NVM SW checksum. If the
3793e26186d4c2f856cf60b9c22863ab0080afbdc66Shannon Nelson * caller does not need checksum, the value can be NULL.
38056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg **/
38156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
38256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg						 u16 *checksum)
38356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg{
38456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	i40e_status ret_code = 0;
38556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	u16 checksum_sr = 0;
386e15c9fa03639fcd30d035ea829f11b222b95e7f3Jesse Brandeburg	u16 checksum_local = 0;
38756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
38856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
38956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (ret_code)
3907a208e83fcedc0b845facc17d05ead0b9b73a967Kamil Krawczyk		goto i40e_validate_nvm_checksum_exit;
39156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
39256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* Do not use i40e_read_nvm_word() because we do not want to take
39356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 * the synchronization semaphores twice here.
39456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 */
395a4bcfbb7067ab04ddd4f48b8ac4da10d62a8de9aShannon Nelson	i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
39656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
39756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* Verify read checksum from EEPROM is the same as
39856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 * calculated checksum
39956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	 */
40056a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (checksum_local != checksum_sr)
40156a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		ret_code = I40E_ERR_NVM_CHECKSUM;
40256a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
40356a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	/* If the user cares, return the calculated checksum */
40456a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	if (checksum)
40556a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg		*checksum = checksum_local;
40656a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg
40756a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburgi40e_validate_nvm_checksum_exit:
40856a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg	return ret_code;
40956a62fc8689509fb86bcb20768d575b81d9c311eJesse Brandeburg}
410cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
411cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
412cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					  struct i40e_nvm_access *cmd,
413cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					  u8 *bytes, int *errno);
414cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
415cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     struct i40e_nvm_access *cmd,
416cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     u8 *bytes, int *errno);
417cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
418cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     struct i40e_nvm_access *cmd,
419cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     u8 *bytes, int *errno);
420cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
421cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson						struct i40e_nvm_access *cmd,
422cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson						int *errno);
423cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
424cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 struct i40e_nvm_access *cmd,
425cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 int *errno);
426cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
427cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 struct i40e_nvm_access *cmd,
428cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 u8 *bytes, int *errno);
429cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
430cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					struct i40e_nvm_access *cmd,
431cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					u8 *bytes, int *errno);
432cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic inline u8 i40e_nvmupd_get_module(u32 val)
433cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
434cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return (u8)(val & I40E_NVM_MOD_PNT_MASK);
435cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
436cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic inline u8 i40e_nvmupd_get_transaction(u32 val)
437cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
438cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
439cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
440cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
441cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
442cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_command - Process an NVM update command
443cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
444cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command
445cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @bytes: pointer to the data buffer
446cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
447cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
448cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * Dispatches command depending on what update state is current
449cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
450cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsoni40e_status i40e_nvmupd_command(struct i40e_hw *hw,
451cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				struct i40e_nvm_access *cmd,
452cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				u8 *bytes, int *errno)
453cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
454cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status;
455cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
456cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	/* assume success */
457cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	*errno = 0;
458cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
459cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	switch (hw->nvmupd_state) {
460cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_STATE_INIT:
461cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
462cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
463cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
464cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_STATE_READING:
465cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
466cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
467cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
468cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_STATE_WRITING:
469cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
470cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
471cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
472cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	default:
473cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		/* invalid state, should never happen */
474cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = I40E_NOT_SUPPORTED;
475cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = -ESRCH;
476cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
477cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
478cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
479cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
480cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
481cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
482cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_state_init - Handle NVM update state Init
483cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
484cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
485cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @bytes: pointer to the data buffer
486cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
487cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
488cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * Process legitimate commands of the Init state and conditionally set next
489cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * state. Reject all other commands.
490cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
491cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
492cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					  struct i40e_nvm_access *cmd,
493cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					  u8 *bytes, int *errno)
494cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
495cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status = 0;
496cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	enum i40e_nvmupd_cmd upd_cmd;
497cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
498cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
499cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
500cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	switch (upd_cmd) {
501cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_READ_SA:
502cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
503cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
504cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
505cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
506cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
507cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			i40e_release_nvm(hw);
508cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
509cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
510cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
511cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_READ_SNT:
512cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
513cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
514cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
515cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
516cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
517cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
518cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
519cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
520cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
521cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_WRITE_ERA:
522cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
523cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
524cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
525cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
526cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
527cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			if (status)
528cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				i40e_release_nvm(hw);
529cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			else
530cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				hw->aq.nvm_release_on_done = true;
531cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
532cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
533cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
534cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_WRITE_SA:
535cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
536cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
537cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
538cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
539cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
540cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			if (status)
541cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				i40e_release_nvm(hw);
542cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			else
543cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				hw->aq.nvm_release_on_done = true;
544cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
545cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
546cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
547cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_WRITE_SNT:
548cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
549cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
550cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
551cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
552cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
553cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
554cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
555cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
556cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
557cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_CSUM_SA:
558cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
559cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
560cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
561cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
562cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			status = i40e_update_nvm_checksum(hw);
563cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			if (status) {
564cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				*errno = hw->aq.asq_last_status ?
565cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
566cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   -EIO;
567cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				i40e_release_nvm(hw);
568cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			} else {
569cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				hw->aq.nvm_release_on_done = true;
570cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			}
571cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
572cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
573cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
574cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	default:
575cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = I40E_ERR_NVM;
576cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = -ESRCH;
577cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
578cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
579cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
580cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
581cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
582cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
583cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_state_reading - Handle NVM update state Reading
584cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
585cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
586cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @bytes: pointer to the data buffer
587cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
588cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
589cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * NVM ownership is already held.  Process legitimate commands and set any
590cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * change in state; reject all other commands.
591cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
592cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
593cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     struct i40e_nvm_access *cmd,
594cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     u8 *bytes, int *errno)
595cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
596cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status;
597cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	enum i40e_nvmupd_cmd upd_cmd;
598cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
599cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
600cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
601cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	switch (upd_cmd) {
602cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_READ_SA:
603cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_READ_CON:
604cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
605cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
606cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
607cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_READ_LCB:
608cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
609cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		i40e_release_nvm(hw);
610cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
611cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
612cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
613cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	default:
614cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = I40E_NOT_SUPPORTED;
615cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = -ESRCH;
616cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
617cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
618cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
619cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
620cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
621cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
622cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_state_writing - Handle NVM update state Writing
623cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
624cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
625cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @bytes: pointer to the data buffer
626cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
627cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
628cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * NVM ownership is already held.  Process legitimate commands and set any
629cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * change in state; reject all other commands
630cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
631cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
632cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     struct i40e_nvm_access *cmd,
633cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					     u8 *bytes, int *errno)
634cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
635cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status;
636cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	enum i40e_nvmupd_cmd upd_cmd;
637cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
638cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
639cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
640cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	switch (upd_cmd) {
641cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_WRITE_CON:
642cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
643cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
644cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
645cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_WRITE_LCB:
646cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
647cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (!status) {
648cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			hw->aq.nvm_release_on_done = true;
649cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
650cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
651cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
652cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
653cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_CSUM_CON:
654cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_update_nvm_checksum(hw);
655cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status)
656cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = hw->aq.asq_last_status ?
657cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
658cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   -EIO;
659cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
660cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
661cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVMUPD_CSUM_LCB:
662cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = i40e_update_nvm_checksum(hw);
663cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		if (status) {
664cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			*errno = hw->aq.asq_last_status ?
665cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
666cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   -EIO;
667cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		} else {
668cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			hw->aq.nvm_release_on_done = true;
669cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
670cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
671cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
672cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
673cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	default:
674cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		status = I40E_NOT_SUPPORTED;
675cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = -ESRCH;
676cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
677cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
678cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
679cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
680cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
681cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
682cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_validate_command - Validate given command
683cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
684cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
685cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
686cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
687cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * Return one of the valid command types or I40E_NVMUPD_INVALID
688cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
689cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
690cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson						 struct i40e_nvm_access *cmd,
691cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson						 int *errno)
692cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
693cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	enum i40e_nvmupd_cmd upd_cmd;
694cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	u8 transaction, module;
695cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
696cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	/* anything that doesn't match a recognized case is an error */
697cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	upd_cmd = I40E_NVMUPD_INVALID;
698cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
699cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	transaction = i40e_nvmupd_get_transaction(cmd->config);
700cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	module = i40e_nvmupd_get_module(cmd->config);
701cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
702cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	/* limits on data size */
703cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if ((cmd->data_size < 1) ||
704cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	    (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
705cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		hw_dbg(hw, "i40e_nvmupd_validate_command data_size %d\n",
706cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		       cmd->data_size);
707cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = -EFAULT;
708cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		return I40E_NVMUPD_INVALID;
709cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
710cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
711cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	switch (cmd->command) {
712cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVM_READ:
713cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		switch (transaction) {
714cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_CON:
715cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_READ_CON;
716cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
717cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_SNT:
718cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_READ_SNT;
719cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
720cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_LCB:
721cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_READ_LCB;
722cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
723cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_SA:
724cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_READ_SA;
725cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
726cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
727cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
728cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
729cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	case I40E_NVM_WRITE:
730cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		switch (transaction) {
731cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_CON:
732cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_WRITE_CON;
733cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
734cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_SNT:
735cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_WRITE_SNT;
736cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
737cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_LCB:
738cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_WRITE_LCB;
739cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
740cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_SA:
741cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_WRITE_SA;
742cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
743cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_ERA:
744cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_WRITE_ERA;
745cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
746cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case I40E_NVM_CSUM:
747cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_CSUM_CON;
748cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
749cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case (I40E_NVM_CSUM|I40E_NVM_SA):
750cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_CSUM_SA;
751cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
752cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		case (I40E_NVM_CSUM|I40E_NVM_LCB):
753cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			upd_cmd = I40E_NVMUPD_CSUM_LCB;
754cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson			break;
755cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		}
756cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		break;
757cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
758cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
759cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if (upd_cmd == I40E_NVMUPD_INVALID) {
760cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = -EFAULT;
761cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		hw_dbg(hw,
762cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		       "i40e_nvmupd_validate_command returns %d  errno: %d\n",
763cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		       upd_cmd, *errno);
764cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	}
765cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return upd_cmd;
766cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
767cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
768cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
769cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_nvm_read - Read NVM
770cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
771cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
772cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @bytes: pointer to the data buffer
773cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
774cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
775cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * cmd structure contains identifiers and data buffer
776cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
777cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
778cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					struct i40e_nvm_access *cmd,
779cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					u8 *bytes, int *errno)
780cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
781cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status;
782cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	u8 module, transaction;
783cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	bool last;
784cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
785cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	transaction = i40e_nvmupd_get_transaction(cmd->config);
786cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	module = i40e_nvmupd_get_module(cmd->config);
787cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
788cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	hw_dbg(hw, "i40e_nvmupd_nvm_read mod 0x%x  off 0x%x  len 0x%x\n",
789cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	       module, cmd->offset, cmd->data_size);
790cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
791cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
792cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				  bytes, last, NULL);
793cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	hw_dbg(hw, "i40e_nvmupd_nvm_read status %d\n", status);
794cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if (status)
795cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
796cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
797cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
798cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
799cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
800cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
801cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_nvm_erase - Erase an NVM module
802cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
803cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
804cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
805cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
806cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * module, offset, data_size and data are in cmd structure
807cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
808cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
809cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 struct i40e_nvm_access *cmd,
810cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 int *errno)
811cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
812cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status = 0;
813cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	u8 module, transaction;
814cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	bool last;
815cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
816cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	transaction = i40e_nvmupd_get_transaction(cmd->config);
817cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	module = i40e_nvmupd_get_module(cmd->config);
818cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	last = (transaction & I40E_NVM_LCB);
819cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	hw_dbg(hw, "i40e_nvmupd_nvm_erase mod 0x%x  off 0x%x  len 0x%x\n",
820cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	       module, cmd->offset, cmd->data_size);
821cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
822cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				   last, NULL);
823cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	hw_dbg(hw, "i40e_nvmupd_nvm_erase status %d\n", status);
824cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if (status)
825cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
826cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
827cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
828cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
829cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
830cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson/**
831cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * i40e_nvmupd_nvm_write - Write NVM
832cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @hw: pointer to hardware structure
833cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @cmd: pointer to nvm update command buffer
834cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @bytes: pointer to the data buffer
835cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * @errno: pointer to return error code
836cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson *
837cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson * module, offset, data_size and data are in cmd structure
838cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson **/
839cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelsonstatic i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
840cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 struct i40e_nvm_access *cmd,
841cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson					 u8 *bytes, int *errno)
842cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson{
843cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	i40e_status status = 0;
844cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	u8 module, transaction;
845cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	bool last;
846cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
847cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	transaction = i40e_nvmupd_get_transaction(cmd->config);
848cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	module = i40e_nvmupd_get_module(cmd->config);
849cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	last = (transaction & I40E_NVM_LCB);
850cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	hw_dbg(hw, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
851cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	       module, cmd->offset, cmd->data_size);
852cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	status = i40e_aq_update_nvm(hw, module, cmd->offset,
853cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson				    (u16)cmd->data_size, bytes, last, NULL);
854cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	hw_dbg(hw, "i40e_nvmupd_nvm_write status %d\n", status);
855cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	if (status)
856cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson		*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
857cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson
858cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson	return status;
859cd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86cShannon Nelson}
860