diff options
Diffstat (limited to 'sys/dev/ixl/i40e_nvm.c')
-rw-r--r-- | sys/dev/ixl/i40e_nvm.c | 115 |
1 files changed, 111 insertions, 4 deletions
diff --git a/sys/dev/ixl/i40e_nvm.c b/sys/dev/ixl/i40e_nvm.c index 6bcf51d0669a..20ba63a05b4e 100644 --- a/sys/dev/ixl/i40e_nvm.c +++ b/sys/dev/ixl/i40e_nvm.c @@ -367,6 +367,77 @@ enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, } /** + * i40e_read_nvm_module_data - Reads NVM Buffer to specified memory location + * @hw: Pointer to the HW structure + * @module_ptr: Pointer to module in words with respect to NVM beginning + * @module_offset: Offset in words from module start + * @data_offset: Offset in words from reading data area start + * @words_data_size: Words to read from NVM + * @data_ptr: Pointer to memory location where resulting buffer will be stored + **/ +enum i40e_status_code +i40e_read_nvm_module_data(struct i40e_hw *hw, u8 module_ptr, u16 module_offset, + u16 data_offset, u16 words_data_size, u16 *data_ptr) +{ + enum i40e_status_code status; + u16 specific_ptr = 0; + u16 ptr_value = 0; + u16 offset = 0; + + if (module_ptr != 0) { + status = i40e_read_nvm_word(hw, module_ptr, &ptr_value); + if (status != I40E_SUCCESS) { + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm word failed.Error code: %d.\n", + status); + return I40E_ERR_NVM; + } + } +#define I40E_NVM_INVALID_PTR_VAL 0x7FFF +#define I40E_NVM_INVALID_VAL 0xFFFF + + /* Pointer not initialized */ + if (ptr_value == I40E_NVM_INVALID_PTR_VAL || + ptr_value == I40E_NVM_INVALID_VAL) { + i40e_debug(hw, I40E_DEBUG_ALL, "Pointer not initialized.\n"); + return I40E_ERR_BAD_PTR; + } + + /* Check whether the module is in SR mapped area or outside */ + if (ptr_value & I40E_PTR_TYPE) { + /* Pointer points outside of the Shared RAM mapped area */ + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm data failed. Pointer points outside of the Shared RAM mapped area.\n"); + + return I40E_ERR_PARAM; + } else { + /* Read from the Shadow RAM */ + + status = i40e_read_nvm_word(hw, ptr_value + module_offset, + &specific_ptr); + if (status != I40E_SUCCESS) { + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm word failed.Error code: %d.\n", + status); + return I40E_ERR_NVM; + } + + offset = ptr_value + module_offset + specific_ptr + + data_offset; + + status = i40e_read_nvm_buffer(hw, offset, &words_data_size, + data_ptr); + if (status != I40E_SUCCESS) { + i40e_debug(hw, I40E_DEBUG_ALL, + "Reading nvm buffer failed.Error code: %d.\n", + status); + } + } + + return status; +} + +/** * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). @@ -504,10 +575,10 @@ enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, } else { ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data); } + return ret_code; } - /** * i40e_write_nvm_aq - Writes Shadow RAM. * @hw: pointer to the HW structure. @@ -826,6 +897,7 @@ static const char *i40e_nvm_update_state_str[] = { "I40E_NVMUPD_EXEC_AQ", "I40E_NVMUPD_GET_AQ_RESULT", "I40E_NVMUPD_GET_AQ_EVENT", + "I40E_NVMUPD_GET_FEATURES", }; /** @@ -888,6 +960,31 @@ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw, 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, @@ -1354,10 +1451,20 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, upd_cmd = I40E_NVMUPD_READ_SA; break; case I40E_NVM_EXEC: - if (module == 0xf) - upd_cmd = I40E_NVMUPD_STATUS; - else if (module == 0) + switch (module) { + case I40E_NVM_EXEC_GET_AQ_RESULT: upd_cmd = I40E_NVMUPD_GET_AQ_RESULT; + break; + case I40E_NVM_EXEC_FEATURES: + upd_cmd = I40E_NVMUPD_FEATURES; + break; + case I40E_NVM_EXEC_STATUS: + upd_cmd = I40E_NVMUPD_STATUS; + break; + default: + *perrno = -EFAULT; + return I40E_NVMUPD_INVALID; + } break; case I40E_NVM_AQE: upd_cmd = I40E_NVMUPD_GET_AQ_EVENT; |