DPDK patches and discussions
 help / color / mirror / Atom feed
From: Jingjing Wu <jingjing.wu@intel.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH 11/52] i40e/base: add commands to nvmupdate utility
Date: Sun,  6 Sep 2015 15:11:25 +0800	[thread overview]
Message-ID: <1441523526-26202-12-git-send-email-jingjing.wu@intel.com> (raw)
In-Reply-To: <1441523526-26202-1-git-send-email-jingjing.wu@intel.com>

Add a new GetStatus command so that the NVM update tool can query
the current status instead of doing fake write requests to probe for
readiness.
Add a facility to run AQ commands through the nvmupdate utility in order
to allow the update tools to interact with the FW and do special
commands needed for updates and configuration changes.
Add a facility to recover the result of a previously run AQ command.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
---
 drivers/net/i40e/base/i40e_adminq.c |   3 +
 drivers/net/i40e/base/i40e_nvm.c    | 201 ++++++++++++++++++++++++++++++++++--
 drivers/net/i40e/base/i40e_type.h   |   5 +
 3 files changed, 199 insertions(+), 10 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_adminq.c b/drivers/net/i40e/base/i40e_adminq.c
index 7589b39..b2a96fa 100644
--- a/drivers/net/i40e/base/i40e_adminq.c
+++ b/drivers/net/i40e/base/i40e_adminq.c
@@ -687,6 +687,9 @@ enum i40e_status_code i40e_shutdown_adminq(struct i40e_hw *hw)
 	i40e_destroy_spinlock(&hw->aq.asq_spinlock);
 	i40e_destroy_spinlock(&hw->aq.arq_spinlock);
 
+	if (hw->nvm_buff.va)
+		i40e_free_virt_mem(hw, &hw->nvm_buff);
+
 	return ret_code;
 }
 
diff --git a/drivers/net/i40e/base/i40e_nvm.c b/drivers/net/i40e/base/i40e_nvm.c
index f4ea289..14b4e84 100644
--- a/drivers/net/i40e/base/i40e_nvm.c
+++ b/drivers/net/i40e/base/i40e_nvm.c
@@ -704,6 +704,12 @@ STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw,
 STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw,
 						  struct i40e_nvm_access *cmd,
 						  u8 *bytes, int *perrno);
+STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
+						 struct i40e_nvm_access *cmd,
+						 u8 *bytes, int *perrno);
+STATIC enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
+						    struct i40e_nvm_access *cmd,
+						    u8 *bytes, int *perrno);
 STATIC inline u8 i40e_nvmupd_get_module(u32 val)
 {
 	return (u8)(val & I40E_NVM_MOD_PNT_MASK);
@@ -727,6 +733,9 @@ STATIC const char *i40e_nvm_update_state_str[] = {
 	"I40E_NVMUPD_CSUM_CON",
 	"I40E_NVMUPD_CSUM_SA",
 	"I40E_NVMUPD_CSUM_LCB",
+	"I40E_NVMUPD_STATUS",
+	"I40E_NVMUPD_EXEC_AQ",
+	"I40E_NVMUPD_GET_AQ_RESULT",
 };
 
 /**
@@ -743,12 +752,36 @@ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
 					  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\n",
+		   i40e_nvm_update_state_str[upd_cmd],
+		   hw->nvmupd_state,
+		   hw->aq.nvm_release_on_done);
+
+	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) {
+		bytes[0] = hw->nvmupd_state;
+		return I40E_SUCCESS;
+	}
+
 	switch (hw->nvmupd_state) {
 	case I40E_NVMUPD_STATE_INIT:
 		status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
@@ -892,6 +925,14 @@ STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
 		}
 		break;
 
+	case I40E_NVMUPD_EXEC_AQ:
+		status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno);
+		break;
+
+	case I40E_NVMUPD_GET_AQ_RESULT:
+		status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
+		break;
+
 	default:
 		i40e_debug(hw, I40E_DEBUG_NVM,
 			   "NVMUPD: bad cmd %s in init state\n",
@@ -1075,7 +1116,7 @@ STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
 						    int *perrno)
 {
 	enum i40e_nvmupd_cmd upd_cmd;
-	u8 transaction, module;
+	u8 module, transaction;
 
 	DEBUGFUNC("i40e_nvmupd_validate_command\n");
 
@@ -1110,6 +1151,12 @@ STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
 		case I40E_NVM_SA:
 			upd_cmd = I40E_NVMUPD_READ_SA;
 			break;
+		case I40E_NVM_EXEC:
+			if (module == 0xf)
+				upd_cmd = I40E_NVMUPD_STATUS;
+			else if (module == 0)
+				upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
+			break;
 		}
 		break;
 
@@ -1139,21 +1186,155 @@ STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
 		case (I40E_NVM_CSUM|I40E_NVM_LCB):
 			upd_cmd = I40E_NVMUPD_CSUM_LCB;
 			break;
+		case I40E_NVM_EXEC:
+			if (module == 0)
+				upd_cmd = I40E_NVMUPD_EXEC_AQ;
+			break;
 		}
 		break;
 	}
-	i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
-		   i40e_nvm_update_state_str[upd_cmd],
-		   hw->nvmupd_state,
-		   hw->aq.nvm_release_on_done);
 
-	if (upd_cmd == I40E_NVMUPD_INVALID) {
-		*perrno = -EFAULT;
+	return upd_cmd;
+}
+
+/**
+ * i40e_nvmupd_exec_aq - Run an AQ command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
+						 struct i40e_nvm_access *cmd,
+						 u8 *bytes, int *perrno)
+{
+	struct i40e_asq_cmd_details cmd_details;
+	enum i40e_status_code status;
+	struct i40e_aq_desc *aq_desc;
+	u32 buff_size = 0;
+	u8 *buff = NULL;
+	u32 aq_desc_len;
+	u32 aq_data_len;
+
+	i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+	memset(&cmd_details, 0, sizeof(cmd_details));
+	cmd_details.wb_desc = &hw->nvm_wb_desc;
+
+	aq_desc_len = sizeof(struct i40e_aq_desc);
+	memset(&hw->nvm_wb_desc, 0, aq_desc_len);
+
+	/* get the aq descriptor */
+	if (cmd->data_size < aq_desc_len) {
 		i40e_debug(hw, I40E_DEBUG_NVM,
-			   "i40e_nvmupd_validate_command returns %d perrno %d\n",
-			   upd_cmd, *perrno);
+			   "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n",
+			   cmd->data_size, aq_desc_len);
+		*perrno = -EINVAL;
+		return I40E_ERR_PARAM;
 	}
-	return upd_cmd;
+	aq_desc = (struct i40e_aq_desc *)bytes;
+
+	/* if data buffer needed, make sure it's ready */
+	aq_data_len = cmd->data_size - aq_desc_len;
+	buff_size = max(aq_data_len, (u32)LE16_TO_CPU(aq_desc->datalen));
+	if (buff_size) {
+		if (!hw->nvm_buff.va) {
+			status = i40e_allocate_virt_mem(hw, &hw->nvm_buff,
+							hw->aq.asq_buf_size);
+			if (status)
+				i40e_debug(hw, I40E_DEBUG_NVM,
+					   "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n",
+					   status);
+		}
+
+		if (hw->nvm_buff.va) {
+			buff = hw->nvm_buff.va;
+			memcpy(buff, &bytes[aq_desc_len], aq_data_len);
+		}
+	}
+
+	/* and away we go! */
+	status = i40e_asq_send_command(hw, aq_desc, buff,
+				       buff_size, &cmd_details);
+	if (status) {
+		i40e_debug(hw, I40E_DEBUG_NVM,
+			   "i40e_nvmupd_exec_aq err %s aq_err %s\n",
+			   i40e_stat_str(hw, status),
+			   i40e_aq_str(hw, hw->aq.asq_last_status));
+		*perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+	}
+
+	return status;
+}
+
+/**
+ * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+STATIC enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
+						    struct i40e_nvm_access *cmd,
+						    u8 *bytes, int *perrno)
+{
+	u32 aq_total_len;
+	u32 aq_desc_len;
+	int remainder;
+	u8 *buff;
+
+	i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+
+	aq_desc_len = sizeof(struct i40e_aq_desc);
+	aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_wb_desc.datalen);
+
+	/* check offset range */
+	if (cmd->offset > aq_total_len) {
+		i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n",
+			   __func__, cmd->offset, aq_total_len);
+		*perrno = -EINVAL;
+		return I40E_ERR_PARAM;
+	}
+
+	/* check copylength range */
+	if (cmd->data_size > (aq_total_len - cmd->offset)) {
+		int new_len = aq_total_len - cmd->offset;
+
+		i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n",
+			   __func__, cmd->data_size, new_len);
+		cmd->data_size = new_len;
+	}
+
+	remainder = cmd->data_size;
+	if (cmd->offset < aq_desc_len) {
+		u32 len = aq_desc_len - cmd->offset;
+
+		len = min(len, cmd->data_size);
+		i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n",
+			   __func__, cmd->offset, cmd->offset + len);
+
+		buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset;
+		memcpy(bytes, buff, len);
+
+		bytes += len;
+		remainder -= len;
+		buff = hw->nvm_buff.va;
+	} else {
+		buff = (u8 *)hw->nvm_buff.va + (cmd->offset - aq_desc_len);
+	}
+
+	if (remainder > 0) {
+		int start_byte = buff - (u8 *)hw->nvm_buff.va;
+
+		i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n",
+			   __func__, start_byte, start_byte + remainder);
+		memcpy(bytes, buff, remainder);
+	}
+
+	return I40E_SUCCESS;
 }
 
 /**
diff --git a/drivers/net/i40e/base/i40e_type.h b/drivers/net/i40e/base/i40e_type.h
index f9fc35c..4ea9c2d 100644
--- a/drivers/net/i40e/base/i40e_type.h
+++ b/drivers/net/i40e/base/i40e_type.h
@@ -364,6 +364,9 @@ enum i40e_nvmupd_cmd {
 	I40E_NVMUPD_CSUM_CON,
 	I40E_NVMUPD_CSUM_SA,
 	I40E_NVMUPD_CSUM_LCB,
+	I40E_NVMUPD_STATUS,
+	I40E_NVMUPD_EXEC_AQ,
+	I40E_NVMUPD_GET_AQ_RESULT,
 };
 
 enum i40e_nvmupd_state {
@@ -390,6 +393,7 @@ enum i40e_nvmupd_state {
 #define I40E_NVM_SA		(I40E_NVM_SNT | I40E_NVM_LCB)
 #define I40E_NVM_ERA		0x4
 #define I40E_NVM_CSUM		0x8
+#define I40E_NVM_EXEC		0xf
 
 #define I40E_NVM_ADAPT_SHIFT	16
 #define I40E_NVM_ADAPT_MASK	(0xffffULL << I40E_NVM_ADAPT_SHIFT)
@@ -553,6 +557,7 @@ struct i40e_hw {
 	/* state of nvm update process */
 	enum i40e_nvmupd_state nvmupd_state;
 	struct i40e_aq_desc nvm_wb_desc;
+	struct i40e_virt_mem nvm_buff;
 
 	/* HMC info */
 	struct i40e_hmc_info hmc; /* HMC info struct */
-- 
2.4.0

  parent reply	other threads:[~2015-09-06  7:12 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-06  7:11 [dpdk-dev] [PATCH 00/52] update i40e base driver Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 01/52] i40e/base: split device ids into a separate file Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 02/52] i40e/base: Add new device id for 20Gb and Fort pond device Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 03/52] i40e/base: add error status value decoding Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 04/52] i40e/base: Replace sprintf with i40e_debug Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 05/52] i40e/base: Merge Fortville SW 4 admin Q command header Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 06/52] i40e/base: Add module_types and update_link_info Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 07/52] i40e/base: grab the AQ spinlocks before clearing registers Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 08/52] i40e/base: add handling of writeback descriptor Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 09/52] i40e/base: Add info to nvm info struct for OEM version data Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 10/52] i40e/base: add wait states to NVM state machine Jingjing Wu
2015-09-06  7:11 ` Jingjing Wu [this message]
2015-09-06  7:11 ` [dpdk-dev] [PATCH 12/52] i40e/base: Add promiscuous on VLAN support Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 13/52] i40e/base: Add a workaround to drop all flow control frames Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 14/52] i40e/base: Add Debug Dump Internal Data AQ command Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 15/52] i40e/base: OEM Post Update AQ command implementation Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 16/52] i40e/base: add VF capabilities to virtual channel interface Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 17/52] i40e/base: create new BIT and BIT_ULL macros Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 18/52] i40e/base: Add parsing for CEE DCBX TLVs Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 19/52] i40e/base: Prepare the local LLDP MIB in IEEE TLV Format Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 20/52] i40e/base: Refactor PHY structure and add phy_capabilities enum Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 21/52] i40e/base: Store CEE DCBX cfg from firmware and Cache the CEE TLV status Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 22/52] i40e/base: Add some more stats for FD SB and ATR status Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 23/52] i40e/base: Update Flex-10 related device/function capabilities Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 24/52] i40e/base: Wrap the register definitions for PF and VF driver Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 25/52] i40e/base: fix up type clash in i40e_aq_rc_to_posix conversion Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 26/52] i40e/base: Add new link status defines Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 27/52] i40e/base: fixup padding issue in get_cee_dcb_cfg_v1_resp Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 28/52] i40e/base: Add Tx Scheduling related AQ commands Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 29/52] i40e/base: Additional checks for CEE APP priority validity Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 30/52] i40e/base: Add support for pre-allocated pages for pd Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 31/52] i40e/base: clean up unneeded gotos Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 32/52] i40e/base: Handle admin Q timeout when releasing NVM Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 33/52] i40e/base: Add definition of GLINT_CTL register Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 34/52] i40e/base: Add virtchnl op for additional solaris config Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 35/52] i40e/base: drop func from debug print Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 36/52] i40e/base: add new X722 device Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 37/52] i40e/base: Add AQ functions to handle RSS Key and LUT programming Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 38/52] i40e/base: add proxy config admin q functions Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 39/52] i40e/base: add wol config admin queue functions Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 40/52] i40e/base: add WR_CSR_PROT wol/proxy capability parsing Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 41/52] i40e/base: FortPark has additional PCTYPES supported for RSS Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 42/52] i40e/base: FortPark changes to Rx and Tx descriptor for Outer UDP checksum offloads Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 43/52] i40e/base: use INLINE macro for better cross-platform code management Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 44/52] i40e/base: ESS Support Jingjing Wu
2015-09-06  7:11 ` [dpdk-dev] [PATCH 45/52] i40e/base: print FCoE capability reported by the device function Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 46/52] i40e/base: remove useless assignments Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 47/52] i40e/base: Increase pf reset max loop limit Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 48/52] i40e/base: Add FortPark specific registers Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 49/52] i40e/base: Allow for per-device FW API version Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 50/52] i40e/base: Add ATR command bit definition for FortPark Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 51/52] i40e/base: Explicitly assign enum index for VSI type Jingjing Wu
2015-09-06  7:12 ` [dpdk-dev] [PATCH 52/52] eal/common: add new i40e device id Jingjing Wu
2015-09-09  1:53 ` [dpdk-dev] [PATCH 00/52] update i40e base driver Zhang, Helin
2015-10-01 23:38   ` Thomas Monjalon
2015-10-02  8:24     ` Mcnamara, John
2015-10-08  2:46       ` Wu, Jingjing
2015-09-16  7:45 ` Xu, HuilongX

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1441523526-26202-12-git-send-email-jingjing.wu@intel.com \
    --to=jingjing.wu@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).