Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
@@ -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);
}