src/dpdk/drivers/net/i40e/base/i40e_nvm.c
enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
					  struct i40e_nvm_access *cmd,
					  u8 *bytes, int *perrno)
{
	enum i40e_status_code status;
	enum i40e_nvmupd_cmd upd_cmd;

	DEBUGFUNC("i40e_nvmupd_command");

	/* assume success */
	*perrno = 0;

	/* early check for status command and debug msgs */
	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);

	i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d opc 0x%04x cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n",
		   i40e_nvm_update_state_str[upd_cmd],
		   hw->nvmupd_state,
		   hw->nvm_release_on_done, hw->nvm_wait_opcode,
		   cmd->command, cmd->config, cmd->offset, cmd->data_size);

	if (upd_cmd == I40E_NVMUPD_INVALID) {
		*perrno = -EFAULT;
		i40e_debug(hw, I40E_DEBUG_NVM,
			   "i40e_nvmupd_validate_command returns %d errno %d\n",
			   upd_cmd, *perrno);
	}

	/* a status request returns immediately rather than
	 * going into the state machine
	 */
	if (upd_cmd == I40E_NVMUPD_STATUS) {
		if (!cmd->data_size) {
			*perrno = -EFAULT;
			return I40E_ERR_BUF_TOO_SHORT;
		}

		bytes[0] = hw->nvmupd_state;

		if (cmd->data_size >= 4) {
			bytes[1] = 0;
			*((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
		}

		/* Clear error status on read */
		if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;

		return I40E_SUCCESS;
	}

	/*
	 * A supported features request returns immediately
	 * rather than going into state machine
	 */
	if (upd_cmd == I40E_NVMUPD_FEATURES) {
		if (cmd->data_size < hw->nvmupd_features.size) {
			*perrno = -EFAULT;
			return I40E_ERR_BUF_TOO_SHORT;
		}

		/*
		 * If buffer is bigger than i40e_nvmupd_features structure,
		 * make sure the trailing bytes are set to 0x0.
		 */
		if (cmd->data_size > hw->nvmupd_features.size)
			i40e_memset(bytes + hw->nvmupd_features.size, 0x0,
				    cmd->data_size - hw->nvmupd_features.size,
				    I40E_NONDMA_MEM);

		i40e_memcpy(bytes, &hw->nvmupd_features,
			    hw->nvmupd_features.size, I40E_NONDMA_MEM);

		return I40E_SUCCESS;
	}

	/* Clear status even it is not read and log */
	if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
		i40e_debug(hw, I40E_DEBUG_NVM,
			   "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
		hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
	}

	/* Acquire lock to prevent race condition where adminq_task
	 * can execute after i40e_nvmupd_nvm_read/write but before state
	 * variables (nvm_wait_opcode, nvm_release_on_done) are updated.
	 *
	 * During NVMUpdate, it is observed that lock could be held for
	 * ~5ms for most commands. However lock is held for ~60ms for
	 * NVMUPD_CSUM_LCB command.
	 */
	i40e_acquire_spinlock(&hw->aq.arq_spinlock);
	switch (hw->nvmupd_state) {
	case I40E_NVMUPD_STATE_INIT:
		status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
		break;

	case I40E_NVMUPD_STATE_READING:
		status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
		break;

	case I40E_NVMUPD_STATE_WRITING:
		status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
		break;

	case I40E_NVMUPD_STATE_INIT_WAIT:
	case I40E_NVMUPD_STATE_WRITE_WAIT:
		/* if we need to stop waiting for an event, clear
		 * the wait info and return before doing anything else
		 */
		if (cmd->offset == 0xffff) {
			i40e_nvmupd_clear_wait_state(hw);
			status = I40E_SUCCESS;
			break;
		}

		status = I40E_ERR_NOT_READY;
		*perrno = -EBUSY;
		break;

	default:
		/* invalid state, should never happen */
		i40e_debug(hw, I40E_DEBUG_NVM,
			   "NVMUPD: no such state %d\n", hw->nvmupd_state);
		status = I40E_NOT_SUPPORTED;
		*perrno = -ESRCH;
		break;
	}

	i40e_release_spinlock(&hw->aq.arq_spinlock);
	return status;
}
/**
 * i40e_nvmupd_command - Process an NVM update command
 * @hw: pointer to hardware structure
 * @cmd: pointer to nvm update command
 * @bytes: pointer to the data buffer
 * @perrno: pointer to return error code
 *
 * Dispatches command depending on what update state is current
 **/
Process an NVM update command
@hw: pointer to hardware structure
@cmd: pointer to nvm update command
@bytes: pointer to the data buffer
@perrno: pointer to return error code

Dispatches command depending on what update state is current
Process an NVM update command @hw : pointer to hardware structure @cmd : pointer to nvm update command @bytes : pointer to the data buffer @perrno : pointer to return error code Dispatches command depending on what update state is current
enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
					  struct i40e_nvm_access *cmd,
					  u8 *bytes, int *perrno)
{
	enum i40e_status_code status;
	enum i40e_nvmupd_cmd upd_cmd;
	DEBUGFUNC("i40e_nvmupd_command");
	*perrno = 0;
	upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
	i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d opc 0x%04x cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n",
		   i40e_nvm_update_state_str[upd_cmd],
		   hw->nvmupd_state,
		   hw->nvm_release_on_done, hw->nvm_wait_opcode,
		   cmd->command, cmd->config, cmd->offset, cmd->data_size);
	if (upd_cmd == I40E_NVMUPD_INVALID) {
		*perrno = -EFAULT;
		i40e_debug(hw, I40E_DEBUG_NVM,
			   "i40e_nvmupd_validate_command returns %d errno %d\n",
			   upd_cmd, *perrno);
	}
	if (upd_cmd == I40E_NVMUPD_STATUS) {
		if (!cmd->data_size) {
			*perrno = -EFAULT;
			return I40E_ERR_BUF_TOO_SHORT;
		}
		bytes[0] = hw->nvmupd_state;
		if (cmd->data_size >= 4) {
			bytes[1] = 0;
			*((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
		}
		if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
		return I40E_SUCCESS;
	}
	if (upd_cmd == I40E_NVMUPD_FEATURES) {
		if (cmd->data_size < hw->nvmupd_features.size) {
			*perrno = -EFAULT;
			return I40E_ERR_BUF_TOO_SHORT;
		}
		if (cmd->data_size > hw->nvmupd_features.size)
			i40e_memset(bytes + hw->nvmupd_features.size, 0x0,
				    cmd->data_size - hw->nvmupd_features.size,
				    I40E_NONDMA_MEM);
		i40e_memcpy(bytes, &hw->nvmupd_features,
			    hw->nvmupd_features.size, I40E_NONDMA_MEM);
		return I40E_SUCCESS;
	}
	if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
		i40e_debug(hw, I40E_DEBUG_NVM,
			   "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
		hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
	}
	i40e_acquire_spinlock(&hw->aq.arq_spinlock);
	switch (hw->nvmupd_state) {
	case I40E_NVMUPD_STATE_INIT:
		status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
		break;
	case I40E_NVMUPD_STATE_READING:
		status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno);
		break;
	case I40E_NVMUPD_STATE_WRITING:
		status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
		break;
	case I40E_NVMUPD_STATE_INIT_WAIT:
	case I40E_NVMUPD_STATE_WRITE_WAIT:
		if (cmd->offset == 0xffff) {
			i40e_nvmupd_clear_wait_state(hw);
			status = I40E_SUCCESS;
			break;
		}
		status = I40E_ERR_NOT_READY;
		*perrno = -EBUSY;
		break;
	default:
		i40e_debug(hw, I40E_DEBUG_NVM,
			   "NVMUPD: no such state %d\n", hw->nvmupd_state);
		status = I40E_NOT_SUPPORTED;
		*perrno = -ESRCH;
		break;
	}
	i40e_release_spinlock(&hw->aq.arq_spinlock);
	return status;
}
enum i40e_status_code i40e_nvmupd_command ( struct i40e_hw * hw , struct i40e_nvm_access * cmd , u8 * bytes , int * perrno ) { enum i40e_status_code status ; enum i40e_nvmupd_cmd upd_cmd ; DEBUGFUNC ( " " ) ; * perrno = 0 ; upd_cmd = i40e_nvmupd_validate_command ( hw , cmd , perrno ) ; i40e_debug ( hw , I40E_DEBUG_NVM , " \n " , i40e_nvm_update_state_str [ upd_cmd ] , hw -> nvmupd_state , hw -> nvm_release_on_done , hw -> nvm_wait_opcode , cmd -> command , cmd -> config , cmd -> offset , cmd -> data_size ) ; if ( upd_cmd == I40E_NVMUPD_INVALID ) { * perrno = - EFAULT ; i40e_debug ( hw , I40E_DEBUG_NVM , " \n " , upd_cmd , * perrno ) ; } if ( upd_cmd == I40E_NVMUPD_STATUS ) { if ( ! cmd -> data_size ) { * perrno = - EFAULT ; return I40E_ERR_BUF_TOO_SHORT ; } bytes [ 0 ] = hw -> nvmupd_state ; if ( cmd -> data_size >= 4 ) { bytes [ 1 ] = 0 ; * ( ( u16 * ) & bytes [ 2 ] ) = hw -> nvm_wait_opcode ; } if ( hw -> nvmupd_state == I40E_NVMUPD_STATE_ERROR ) hw -> nvmupd_state = I40E_NVMUPD_STATE_INIT ; return I40E_SUCCESS ; } if ( upd_cmd == I40E_NVMUPD_FEATURES ) { if ( cmd -> data_size < hw -> nvmupd_features . size ) { * perrno = - EFAULT ; return I40E_ERR_BUF_TOO_SHORT ; } if ( cmd -> data_size > hw -> nvmupd_features . size ) i40e_memset ( bytes + hw -> nvmupd_features . size , 0x0 , cmd -> data_size - hw -> nvmupd_features . size , I40E_NONDMA_MEM ) ; i40e_memcpy ( bytes , & hw -> nvmupd_features , hw -> nvmupd_features . size , I40E_NONDMA_MEM ) ; return I40E_SUCCESS ; } if ( hw -> nvmupd_state == I40E_NVMUPD_STATE_ERROR ) { i40e_debug ( hw , I40E_DEBUG_NVM , " \n " ) ; hw -> nvmupd_state = I40E_NVMUPD_STATE_INIT ; } i40e_acquire_spinlock ( & hw -> aq . arq_spinlock ) ; switch ( hw -> nvmupd_state ) { case I40E_NVMUPD_STATE_INIT : status = i40e_nvmupd_state_init ( hw , cmd , bytes , perrno ) ; break ; case I40E_NVMUPD_STATE_READING : status = i40e_nvmupd_state_reading ( hw , cmd , bytes , perrno ) ; break ; case I40E_NVMUPD_STATE_WRITING : status = i40e_nvmupd_state_writing ( hw , cmd , bytes , perrno ) ; break ; case I40E_NVMUPD_STATE_INIT_WAIT : case I40E_NVMUPD_STATE_WRITE_WAIT : if ( cmd -> offset == 0xffff ) { i40e_nvmupd_clear_wait_state ( hw ) ; status = I40E_SUCCESS ; break ; } status = I40E_ERR_NOT_READY ; * perrno = - EBUSY ; break ; default : i40e_debug ( hw , I40E_DEBUG_NVM , " \n " , hw -> nvmupd_state ) ; status = I40E_NOT_SUPPORTED ; * perrno = - ESRCH ; break ; } i40e_release_spinlock ( & hw -> aq . arq_spinlock ) ; return status ; }
i40e_nvmupd_command - Process an NVM update command
 @hw: pointer to hardware structure
 @cmd: pointer to nvm update command
 @bytes: pointer to the data buffer
 @perrno: pointer to return error code
i40e_nvmupd_command - Process an NVM update command @hw : pointer to hardware structure @cmd : pointer to nvm update command @bytes : pointer to the data buffer @perrno : pointer to return error code
/* assume success */ /* early check for status command and debug msgs */ /* a status request returns immediately rather than
	 * going into the state machine
	 */ /* Clear error status on read */ /*
	 * A supported features request returns immediately
	 * rather than going into state machine
	 */ /*
		 * If buffer is bigger than i40e_nvmupd_features structure,
		 * make sure the trailing bytes are set to 0x0.
		 */ /* Clear status even it is not read and log */ /* Acquire lock to prevent race condition where adminq_task
	 * can execute after i40e_nvmupd_nvm_read/write but before state
	 * variables (nvm_wait_opcode, nvm_release_on_done) are updated.
	 *
	 * During NVMUpdate, it is observed that lock could be held for
	 * ~5ms for most commands. However lock is held for ~60ms for
	 * NVMUPD_CSUM_LCB command.
	 */ /* if we need to stop waiting for an event, clear
		 * the wait info and return before doing anything else
		 */ /* invalid state, should never happen */