Commit 7073f46e authored by Shannon Nelson's avatar Shannon Nelson Committed by Jeff Kirsher

i40e: Add AQ commands for NVM Update for X722

X722 does NVM update via the adminq queue, so we need to add support for
that.
Signed-off-by: default avatarShannon Nelson <shannon.nelson@intel.com>
Signed-off-by: default avatarCatherine Sullivan <catherine.sullivan@intel.com>
Tested-by: default avatarJim Young <james.m.young@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 52eb95ef
......@@ -211,6 +211,74 @@ static i40e_status i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,
return ret_code;
}
/**
* i40e_read_nvm_aq - Read Shadow RAM.
* @hw: pointer to the HW structure.
* @module_pointer: module pointer location in words from the NVM beginning
* @offset: offset in words from module start
* @words: number of words to write
* @data: buffer with words to write to the Shadow RAM
* @last_command: tells the AdminQ that this is the last command
*
* Writes a 16 bit words buffer to the Shadow RAM using the admin command.
**/
static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 words, void *data,
bool last_command)
{
i40e_status ret_code = I40E_ERR_NVM;
struct i40e_asq_cmd_details cmd_details;
memset(&cmd_details, 0, sizeof(cmd_details));
/* Here we are checking the SR limit only for the flat memory model.
* We cannot do it for the module-based model, as we did not acquire
* the NVM resource yet (we cannot get the module pointer value).
* Firmware will check the module-based model.
*/
if ((offset + words) > hw->nvm.sr_size)
i40e_debug(hw, I40E_DEBUG_NVM,
"NVM write error: offset %d beyond Shadow RAM limit %d\n",
(offset + words), hw->nvm.sr_size);
else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
/* We can write only up to 4KB (one sector), in one AQ write */
i40e_debug(hw, I40E_DEBUG_NVM,
"NVM write fail error: tried to write %d words, limit is %d.\n",
words, I40E_SR_SECTOR_SIZE_IN_WORDS);
else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
!= (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
/* A single write cannot spread over two sectors */
i40e_debug(hw, I40E_DEBUG_NVM,
"NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
offset, words);
else
ret_code = i40e_aq_read_nvm(hw, module_pointer,
2 * offset, /*bytes*/
2 * words, /*bytes*/
data, last_command, &cmd_details);
return ret_code;
}
/**
* i40e_read_nvm_word_aq - Reads Shadow RAM via AQ
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
* @data: word read from the Shadow RAM
*
* Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
**/
static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
u16 *data)
{
i40e_status ret_code = I40E_ERR_TIMEOUT;
ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, true);
*data = le16_to_cpu(*(__le16 *)data);
return ret_code;
}
/**
* i40e_read_nvm_word - Reads Shadow RAM
* @hw: pointer to the HW structure
......@@ -222,6 +290,8 @@ static i40e_status i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset,
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
u16 *data)
{
if (hw->mac.type == I40E_MAC_X722)
return i40e_read_nvm_word_aq(hw, offset, data);
return i40e_read_nvm_word_srctl(hw, offset, data);
}
......@@ -256,6 +326,63 @@ static i40e_status i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
return ret_code;
}
/**
* i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
* @words: (in) number of words to read; (out) number of words actually read
* @data: words read from the Shadow RAM
*
* Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq()
* method. The buffer read is preceded by the NVM ownership take
* and followed by the release.
**/
static i40e_status i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset,
u16 *words, u16 *data)
{
i40e_status ret_code;
u16 read_size = *words;
bool last_cmd = false;
u16 words_read = 0;
u16 i = 0;
do {
/* Calculate number of bytes we should read in this step.
* FVL AQ do not allow to read more than one page at a time or
* to cross page boundaries.
*/
if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS)
read_size = min(*words,
(u16)(I40E_SR_SECTOR_SIZE_IN_WORDS -
(offset % I40E_SR_SECTOR_SIZE_IN_WORDS)));
else
read_size = min((*words - words_read),
I40E_SR_SECTOR_SIZE_IN_WORDS);
/* Check if this is last command, if so set proper flag */
if ((words_read + read_size) >= *words)
last_cmd = true;
ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size,
data + words_read, last_cmd);
if (ret_code)
goto read_nvm_buffer_aq_exit;
/* Increment counter for words already read and move offset to
* new read location
*/
words_read += read_size;
offset += read_size;
} while (words_read < *words);
for (i = 0; i < *words; i++)
data[i] = le16_to_cpu(((__le16 *)data)[i]);
read_nvm_buffer_aq_exit:
*words = words_read;
return ret_code;
}
/**
* i40e_read_nvm_buffer - Reads Shadow RAM buffer
* @hw: pointer to the HW structure
......@@ -270,6 +397,8 @@ static i40e_status i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset,
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
u16 *words, u16 *data)
{
if (hw->mac.type == I40E_MAC_X722)
return i40e_read_nvm_buffer_aq(hw, offset, words, data);
return i40e_read_nvm_buffer_srctl(hw, offset, words, data);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment