All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/4] qed*: Flash upgrade support.
@ 2018-03-26 10:13 Sudarsana Reddy Kalluru
  2018-03-26 10:13 ` [PATCH net-next 1/4] qed: Populate nvm image attribute shadow Sudarsana Reddy Kalluru
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Sudarsana Reddy Kalluru @ 2018-03-26 10:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior, Sudarsana Reddy Kalluru

From: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>

The patch series adds adapter flash upgrade support for qed/qede drivers.

Please consider applying it to net-next branch.

Sudarsana Reddy Kalluru (4):
  qed: Populate nvm image attribute shadow.
  qed: Add APIs for flash access.
  qed: Adapter flash update support.
  qede: Ethtool flash update support.

 drivers/net/ethernet/qlogic/qed/qed.h           |  15 ++
 drivers/net/ethernet/qlogic/qed/qed_dev.c       |  19 +-
 drivers/net/ethernet/qlogic/qed/qed_hsi.h       |   7 +-
 drivers/net/ethernet/qlogic/qed/qed_main.c      | 338 ++++++++++++++++++++++++
 drivers/net/ethernet/qlogic/qed/qed_mcp.c       | 219 +++++++++++++--
 drivers/net/ethernet/qlogic/qed/qed_mcp.h       |  56 +++-
 drivers/net/ethernet/qlogic/qed/qed_selftest.c  |   9 +-
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c |   9 +
 include/linux/qed/qed_if.h                      |  17 ++
 9 files changed, 650 insertions(+), 39 deletions(-)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH net-next 1/4] qed: Populate nvm image attribute shadow.
  2018-03-26 10:13 [PATCH net-next 0/4] qed*: Flash upgrade support Sudarsana Reddy Kalluru
@ 2018-03-26 10:13 ` Sudarsana Reddy Kalluru
  2018-03-27 13:01   ` Yuval Mintz
  2018-03-26 10:13 ` [PATCH net-next 2/4] qed: Add APIs for flash access Sudarsana Reddy Kalluru
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Sudarsana Reddy Kalluru @ 2018-03-26 10:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior

This patch add support for populating the flash image attributes.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed.h          |  8 +++
 drivers/net/ethernet/qlogic/qed/qed_dev.c      | 19 ++++-
 drivers/net/ethernet/qlogic/qed/qed_mcp.c      | 96 +++++++++++++++++++-------
 drivers/net/ethernet/qlogic/qed/qed_mcp.h      | 22 ++++--
 drivers/net/ethernet/qlogic/qed/qed_selftest.c |  9 +--
 5 files changed, 116 insertions(+), 38 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 6948855..b409499 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -437,6 +437,11 @@ enum BAR_ID {
 	BAR_ID_1		/* Used for doorbells */
 };
 
+struct qed_nvm_image_info {
+	u32 num_images;
+	struct bist_nvm_image_att *image_att;
+};
+
 #define DRV_MODULE_VERSION		      \
 	__stringify(QED_MAJOR_VERSION) "."    \
 	__stringify(QED_MINOR_VERSION) "."    \
@@ -561,6 +566,9 @@ struct qed_hwfn {
 	/* L2-related */
 	struct qed_l2_info *p_l2_info;
 
+	/* Nvm images number and attributes */
+	struct qed_nvm_image_info nvm_info;
+
 	struct qed_ptt *p_arfs_ptt;
 
 	struct qed_simd_fp_handler	simd_proto_handler[64];
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 553a6d1..6469d79 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -2930,6 +2930,12 @@ static int qed_get_dev_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 	return 0;
 }
 
+static void qed_nvm_info_free(struct qed_hwfn *p_hwfn)
+{
+	kfree(p_hwfn->nvm_info.image_att);
+	p_hwfn->nvm_info.image_att = NULL;
+}
+
 static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
 				 void __iomem *p_regview,
 				 void __iomem *p_doorbells,
@@ -2993,12 +2999,21 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
 			DP_NOTICE(p_hwfn, "Failed to initiate PF FLR\n");
 	}
 
+	/* NVRAM info initialization and population */
+	rc = qed_mcp_nvm_info_populate(p_hwfn);
+	if (rc) {
+		DP_NOTICE(p_hwfn, "Failed to populate nvm info shadow\n");
+		goto err2;
+	}
+
 	/* Allocate the init RT array and initialize the init-ops engine */
 	rc = qed_init_alloc(p_hwfn);
 	if (rc)
-		goto err2;
+		goto err3;
 
 	return rc;
+err3:
+	qed_nvm_info_free(p_hwfn);
 err2:
 	if (IS_LEAD_HWFN(p_hwfn))
 		qed_iov_free_hw_info(p_hwfn->cdev);
@@ -3054,6 +3069,7 @@ int qed_hw_prepare(struct qed_dev *cdev,
 		if (rc) {
 			if (IS_PF(cdev)) {
 				qed_init_free(p_hwfn);
+				qed_nvm_info_free(p_hwfn);
 				qed_mcp_free(p_hwfn);
 				qed_hw_hwfn_free(p_hwfn);
 			}
@@ -3081,6 +3097,7 @@ void qed_hw_remove(struct qed_dev *cdev)
 		}
 
 		qed_init_free(p_hwfn);
+		qed_nvm_info_free(p_hwfn);
 		qed_hw_hwfn_free(p_hwfn);
 		qed_mcp_free(p_hwfn);
 	}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 6f46cb1..6bf95e4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -2303,9 +2303,9 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 	return rc;
 }
 
-int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
-					 struct qed_ptt *p_ptt,
-					 u32 *num_images)
+int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn,
+				    struct qed_ptt *p_ptt,
+				    u32 *num_images)
 {
 	u32 drv_mb_param = 0, rsp;
 	int rc = 0;
@@ -2324,9 +2324,9 @@ int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
 	return rc;
 }
 
-int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
-					struct qed_ptt *p_ptt,
-					struct bist_nvm_image_att *p_image_att,
+int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn,
+				   struct qed_ptt *p_ptt,
+				   struct bist_nvm_image_att *p_image_att,
 					u32 image_index)
 {
 	u32 buf_size = 0, param, resp = 0, resp_param = 0;
@@ -2351,16 +2351,71 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
 	return rc;
 }
 
+int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn)
+{
+	struct qed_nvm_image_info *nvm_info = &p_hwfn->nvm_info;
+	struct qed_ptt *p_ptt;
+	int rc;
+	u32 i;
+
+	p_ptt = qed_ptt_acquire(p_hwfn);
+	if (!p_ptt) {
+		DP_ERR(p_hwfn, "failed to acquire ptt\n");
+		return -EBUSY;
+	}
+
+	/* Acquire from MFW the amount of available images */
+	nvm_info->num_images = 0;
+	rc = qed_mcp_bist_nvm_get_num_images(p_hwfn,
+					     p_ptt, &nvm_info->num_images);
+	if (rc == -EOPNOTSUPP) {
+		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+		goto out;
+	} else if ((rc != 0) || (nvm_info->num_images == 0)) {
+		DP_ERR(p_hwfn, "Failed getting number of images\n");
+		goto err0;
+	}
+
+	nvm_info->image_att =
+	    kmalloc(nvm_info->num_images * sizeof(struct bist_nvm_image_att),
+		    GFP_KERNEL);
+	if (!nvm_info->image_att) {
+		rc = -ENOMEM;
+		goto err0;
+	}
+
+	/* Iterate over images and get their attributes */
+	for (i = 0; i < nvm_info->num_images; i++) {
+		rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						    &nvm_info->image_att[i], i);
+		if (rc) {
+			DP_ERR(p_hwfn,
+			       "Failed getting image index %d attributes\n", i);
+			goto err1;
+		}
+
+		DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n", i,
+			   nvm_info->image_att[i].len);
+	}
+out:
+	qed_ptt_release(p_hwfn, p_ptt);
+	return 0;
+
+err1:
+	kfree(nvm_info->image_att);
+err0:
+	qed_ptt_release(p_hwfn, p_ptt);
+	return rc;
+}
+
 static int
 qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
 			  struct qed_ptt *p_ptt,
 			  enum qed_nvm_images image_id,
 			  struct qed_nvm_image_att *p_image_att)
 {
-	struct bist_nvm_image_att mfw_image_att;
 	enum nvm_image_type type;
-	u32 num_images, i;
-	int rc;
+	u32 i;
 
 	/* Translate image_id into MFW definitions */
 	switch (image_id) {
@@ -2376,29 +2431,18 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
 		return -EINVAL;
 	}
 
-	/* Learn number of images, then traverse and see if one fits */
-	rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
-	if (rc || !num_images)
-		return -EINVAL;
-
-	for (i = 0; i < num_images; i++) {
-		rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
-							 &mfw_image_att, i);
-		if (rc)
-			return rc;
-
-		if (type == mfw_image_att.image_type)
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
+		if (type == p_hwfn->nvm_info.image_att[i].image_type)
 			break;
-	}
-	if (i == num_images) {
+	if (i == p_hwfn->nvm_info.num_images) {
 		DP_VERBOSE(p_hwfn, QED_MSG_STORAGE,
 			   "Failed to find nvram image of type %08x\n",
 			   image_id);
-		return -EINVAL;
+		return -ENOENT;
 	}
 
-	p_image_att->start_addr = mfw_image_att.nvm_start_addr;
-	p_image_att->length = mfw_image_att.len;
+	p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index c7ec239..7d33354 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -496,9 +496,9 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn,
  *
  * @return int - 0 - operation was successful.
  */
-int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
-					 struct qed_ptt *p_ptt,
-					 u32 *num_images);
+int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn,
+				    struct qed_ptt *p_ptt,
+				    u32 *num_images);
 
 /**
  * @brief Bist nvm test - get image attributes by index
@@ -510,10 +510,10 @@ int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
  *
  * @return int - 0 - operation was successful.
  */
-int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
-					struct qed_ptt *p_ptt,
-					struct bist_nvm_image_att *p_image_att,
-					u32 image_index);
+int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn,
+				   struct qed_ptt *p_ptt,
+				   struct bist_nvm_image_att *p_image_att,
+				   u32 image_index);
 
 /* Using hwfn number (and not pf_num) is required since in CMT mode,
  * same pf_num may be used by two different hwfn
@@ -957,4 +957,12 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
  * @param p_ptt
  */
 int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+
+/**
+ * @brief Populate the nvm info shadow in the given hardware function
+ *
+ * @param p_hwfn
+ */
+int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn);
+
 #endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.c b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
index 1bafc05..cf1d447 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_selftest.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
@@ -125,10 +125,11 @@ int qed_selftest_nvram(struct qed_dev *cdev)
 	}
 
 	/* Acquire from MFW the amount of available images */
-	rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
+	rc = qed_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt, &num_images);
 	if (rc || !num_images) {
 		DP_ERR(p_hwfn, "Failed getting number of images\n");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto err0;
 	}
 
 	/* Iterate over images and validate CRC */
@@ -136,8 +137,8 @@ int qed_selftest_nvram(struct qed_dev *cdev)
 		/* This mailbox returns information about the image required for
 		 * reading it.
 		 */
-		rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
-							 &image_att, i);
+		rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+						    &image_att, i);
 		if (rc) {
 			DP_ERR(p_hwfn,
 			       "Failed getting image index %d attributes\n",
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net-next 2/4] qed: Add APIs for flash access.
  2018-03-26 10:13 [PATCH net-next 0/4] qed*: Flash upgrade support Sudarsana Reddy Kalluru
  2018-03-26 10:13 ` [PATCH net-next 1/4] qed: Populate nvm image attribute shadow Sudarsana Reddy Kalluru
@ 2018-03-26 10:13 ` Sudarsana Reddy Kalluru
  2018-03-26 10:13 ` [PATCH net-next 3/4] qed: Adapter flash update support Sudarsana Reddy Kalluru
  2018-03-26 10:13 ` [PATCH net-next 4/4] qede: Ethtool " Sudarsana Reddy Kalluru
  3 siblings, 0 replies; 8+ messages in thread
From: Sudarsana Reddy Kalluru @ 2018-03-26 10:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior

This patch adds APIs for flash access.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed.h     |   7 ++
 drivers/net/ethernet/qlogic/qed/qed_hsi.h |   7 +-
 drivers/net/ethernet/qlogic/qed/qed_mcp.c | 123 ++++++++++++++++++++++++++++++
 drivers/net/ethernet/qlogic/qed/qed_mcp.h |  34 +++++++++
 4 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index b409499..e07460a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -81,6 +81,13 @@ enum qed_coalescing_mode {
 	QED_COAL_MODE_ENABLE
 };
 
+enum qed_nvm_cmd {
+	QED_PUT_FILE_BEGIN = DRV_MSG_CODE_NVM_PUT_FILE_BEGIN,
+	QED_PUT_FILE_DATA = DRV_MSG_CODE_NVM_PUT_FILE_DATA,
+	QED_NVM_WRITE_NVRAM = DRV_MSG_CODE_NVM_WRITE_NVRAM,
+	QED_GET_MCP_NVM_RESP = 0xFFFFFF00
+};
+
 struct qed_eth_cb_ops;
 struct qed_dev_info;
 union qed_mcp_protocol_stats;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index de873d7..ea3cfe9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12210,8 +12210,11 @@ struct public_drv_mb {
 #define DRV_MSG_CODE_VF_DISABLED_DONE		0xc0000000
 #define DRV_MSG_CODE_CFG_VF_MSIX		0xc0010000
 #define DRV_MSG_CODE_CFG_PF_VFS_MSIX		0xc0020000
+#define DRV_MSG_CODE_NVM_PUT_FILE_BEGIN		0x00010000
+#define DRV_MSG_CODE_NVM_PUT_FILE_DATA		0x00020000
 #define DRV_MSG_CODE_NVM_GET_FILE_ATT		0x00030000
 #define DRV_MSG_CODE_NVM_READ_NVRAM		0x00050000
+#define DRV_MSG_CODE_NVM_WRITE_NVRAM		0x00060000
 #define DRV_MSG_CODE_MCP_RESET			0x00090000
 #define DRV_MSG_CODE_SET_VERSION		0x000f0000
 #define DRV_MSG_CODE_MCP_HALT                   0x00100000
@@ -12265,7 +12268,6 @@ struct public_drv_mb {
 
 #define DRV_MSG_CODE_FEATURE_SUPPORT		0x00300000
 #define DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT	0x00310000
-
 #define DRV_MSG_SEQ_NUMBER_MASK			0x0000ffff
 
 	u32 drv_mb_param;
@@ -12377,7 +12379,10 @@ struct public_drv_mb {
 #define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE	0xb0010000
 
 #define FW_MSG_CODE_NVM_OK			0x00010000
+#define FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK	0x00400000
+#define FW_MSG_CODE_PHY_OK			0x00110000
 #define FW_MSG_CODE_OK				0x00160000
+#define FW_MSG_CODE_ERROR			0x00170000
 
 #define FW_MSG_CODE_OS_WOL_SUPPORTED            0x00800000
 #define FW_MSG_CODE_OS_WOL_NOT_SUPPORTED        0x00810000
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 6bf95e4..de58960 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -569,6 +569,31 @@ int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
 	return 0;
 }
 
+int qed_mcp_nvm_wr_cmd(struct qed_hwfn *p_hwfn,
+		       struct qed_ptt *p_ptt,
+		       u32 cmd,
+		       u32 param,
+		       u32 *o_mcp_resp,
+		       u32 *o_mcp_param, u32 i_txn_size, u32 *i_buf)
+{
+	struct qed_mcp_mb_params mb_params;
+	int rc;
+
+	memset(&mb_params, 0, sizeof(mb_params));
+	mb_params.cmd = cmd;
+	mb_params.param = param;
+	mb_params.p_data_src = i_buf;
+	mb_params.data_src_size = (u8)i_txn_size;
+	rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+	if (rc)
+		return rc;
+
+	*o_mcp_resp = mb_params.mcp_resp;
+	*o_mcp_param = mb_params.mcp_param;
+
+	return 0;
+}
+
 int qed_mcp_nvm_rd_cmd(struct qed_hwfn *p_hwfn,
 		       struct qed_ptt *p_ptt,
 		       u32 cmd,
@@ -2261,6 +2286,104 @@ int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len)
 	return rc;
 }
 
+int qed_mcp_nvm_resp(struct qed_dev *cdev, u8 *p_buf)
+{
+	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+	struct qed_ptt *p_ptt;
+
+	p_ptt = qed_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EBUSY;
+
+	memcpy(p_buf, &cdev->mcp_nvm_resp, sizeof(cdev->mcp_nvm_resp));
+	qed_ptt_release(p_hwfn, p_ptt);
+
+	return 0;
+}
+
+int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr)
+{
+	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+	struct qed_ptt *p_ptt;
+	u32 resp, param;
+	int rc;
+
+	p_ptt = qed_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EBUSY;
+	rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_NVM_PUT_FILE_BEGIN, addr,
+			 &resp, &param);
+	cdev->mcp_nvm_resp = resp;
+	qed_ptt_release(p_hwfn, p_ptt);
+
+	return rc;
+}
+
+int qed_mcp_nvm_write(struct qed_dev *cdev,
+		      u32 cmd, u32 addr, u8 *p_buf, u32 len)
+{
+	u32 buf_idx, buf_size, nvm_cmd, nvm_offset, resp = 0, param;
+	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+	struct qed_ptt *p_ptt;
+	int rc = -EINVAL;
+
+	p_ptt = qed_ptt_acquire(p_hwfn);
+	if (!p_ptt)
+		return -EBUSY;
+
+	switch (cmd) {
+	case QED_PUT_FILE_DATA:
+		nvm_cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA;
+		break;
+	case QED_NVM_WRITE_NVRAM:
+		nvm_cmd = DRV_MSG_CODE_NVM_WRITE_NVRAM;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, "Invalid nvm write command 0x%x\n", cmd);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	buf_idx = 0;
+	while (buf_idx < len) {
+		buf_size = min_t(u32, (len - buf_idx), MCP_DRV_NVM_BUF_LEN);
+		nvm_offset = ((buf_size << DRV_MB_PARAM_NVM_LEN_OFFSET) |
+			      addr) + buf_idx;
+		rc = qed_mcp_nvm_wr_cmd(p_hwfn, p_ptt, nvm_cmd, nvm_offset,
+					&resp, &param, buf_size,
+					(u32 *)&p_buf[buf_idx]);
+		if (rc) {
+			DP_NOTICE(cdev,
+				  "%s failed, rc = %d\n", __func__, rc);
+			resp = FW_MSG_CODE_ERROR;
+			break;
+		}
+
+		if (resp != FW_MSG_CODE_OK &&
+		    resp != FW_MSG_CODE_NVM_OK &&
+		    resp != FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK) {
+			DP_NOTICE(cdev,
+				  "nvm write failed, resp = 0x%08x\n", resp);
+			rc = -EINVAL;
+			break;
+		}
+
+		/* This can be a lengthy process, and it's possible scheduler
+		 * isn't pre-emptable. Sleep a bit to prevent CPU hogging.
+		 */
+		if (buf_idx % 0x1000 > (buf_idx + buf_size) % 0x1000)
+			usleep_range(1000, 2000);
+
+		buf_idx += buf_size;
+	}
+
+	cdev->mcp_nvm_resp = resp;
+out:
+	qed_ptt_release(p_hwfn, p_ptt);
+
+	return rc;
+}
+
 int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
 	u32 drv_mb_param = 0, rsp, param;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 7d33354..8a5c988 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -443,6 +443,40 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
  */
 int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len);
 
+/**
+ * @brief Write to nvm
+ *
+ *  @param cdev
+ *  @param addr - nvm offset
+ *  @param cmd - nvm command
+ *  @param p_buf - nvm write buffer
+ *  @param len - buffer len
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_write(struct qed_dev *cdev,
+		      u32 cmd, u32 addr, u8 *p_buf, u32 len);
+
+/**
+ * @brief Put file begin
+ *
+ *  @param cdev
+ *  @param addr - nvm offset
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr);
+
+/**
+ * @brief Check latest response
+ *
+ *  @param cdev
+ *  @param p_buf - nvm write buffer
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_resp(struct qed_dev *cdev, u8 *p_buf);
+
 struct qed_nvm_image_att {
 	u32 start_addr;
 	u32 length;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net-next 3/4] qed: Adapter flash update support.
  2018-03-26 10:13 [PATCH net-next 0/4] qed*: Flash upgrade support Sudarsana Reddy Kalluru
  2018-03-26 10:13 ` [PATCH net-next 1/4] qed: Populate nvm image attribute shadow Sudarsana Reddy Kalluru
  2018-03-26 10:13 ` [PATCH net-next 2/4] qed: Add APIs for flash access Sudarsana Reddy Kalluru
@ 2018-03-26 10:13 ` Sudarsana Reddy Kalluru
  2018-03-27 13:36   ` Yuval Mintz
  2018-03-26 10:13 ` [PATCH net-next 4/4] qede: Ethtool " Sudarsana Reddy Kalluru
  3 siblings, 1 reply; 8+ messages in thread
From: Sudarsana Reddy Kalluru @ 2018-03-26 10:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior

This patch adds the required driver support for updating the flash or
non volatile memory of the adapter. At highlevel, flash upgrade comprises
of reading the flash images from the input file, validating the images and
writing it to the respective paritions.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed_main.c | 338 +++++++++++++++++++++++++++++
 include/linux/qed/qed_if.h                 |  17 ++
 2 files changed, 355 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 2783288..de2fe24 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -45,6 +45,7 @@
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/crash_dump.h>
+#include <linux/crc32.h>
 #include <linux/qed/qed_if.h>
 #include <linux/qed/qed_ll2_if.h>
 
@@ -1553,6 +1554,342 @@ static int qed_drain(struct qed_dev *cdev)
 	return 0;
 }
 
+static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev,
+					  struct qed_nvm_image_att *nvm_image,
+					  u32 *crc)
+{
+	u8 *buf = NULL;
+	int rc, j;
+	u32 val;
+
+	/* Allocate a buffer for holding the nvram image */
+	buf = kzalloc(nvm_image->length, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Read image into buffer */
+	rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr,
+			      buf, nvm_image->length);
+	if (rc) {
+		DP_ERR(cdev, "Failed reading image from nvm\n");
+		goto out;
+	}
+
+	/* Convert the buffer into big-endian format (excluding the
+	 * closing 4 bytes of CRC).
+	 */
+	for (j = 0; j < nvm_image->length - 4; j += 4) {
+		val = cpu_to_be32(*(u32 *)&buf[j]);
+		*(u32 *)&buf[j] = val;
+	}
+
+	/* Calc CRC for the "actual" image buffer, i.e. not including
+	 * the last 4 CRC bytes.
+	 */
+	*crc = (~cpu_to_be32(crc32(0xffffffff, buf, nvm_image->length - 4)));
+
+out:
+	kfree(buf);
+
+	return rc;
+}
+
+/* Binary file format -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x4 [command index]                            |
+ * 4B  | image_type     | Options        |  Number of register settings       |
+ * 8B  |                       Value                                          |
+ * 12B |                       Mask                                           |
+ * 16B |                       Offset                                         |
+ *     \----------------------------------------------------------------------/
+ * There can be several Value-Mask-Offset sets as specified by 'Number of...'.
+ * Options - 0'b - Calculate & Update CRC for image
+ */
+static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
+				      bool *check_resp)
+{
+	struct qed_nvm_image_att nvm_image;
+	struct qed_hwfn *p_hwfn;
+	bool is_crc = false;
+	u32 image_type;
+	int rc = 0, i;
+	u16 len;
+
+	*data += 4;
+	image_type = **data;
+	p_hwfn = QED_LEADING_HWFN(cdev);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
+		if (image_type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_ERR(cdev, "Failed to find nvram image of type %08x\n",
+		       image_type);
+		return -ENOENT;
+	}
+
+	nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	nvm_image.length = p_hwfn->nvm_info.image_att[i].len;
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n",
+		   **data, nvm_image.start_addr, image_type,
+		   nvm_image.start_addr + nvm_image.length - 1);
+	(*data)++;
+	is_crc = !!(**data);
+	(*data)++;
+	len = *((u16 *)*data);
+	*data += 2;
+	if (is_crc) {
+		u32 crc = 0;
+
+		rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc);
+		if (rc) {
+			DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc);
+			goto exit;
+		}
+
+		rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
+				       (nvm_image.start_addr +
+					nvm_image.length - 4), (u8 *)&crc, 4);
+		if (rc)
+			DP_ERR(cdev, "Failed writing to %08x, rc = %d\n",
+			       nvm_image.start_addr + nvm_image.length - 4, rc);
+		goto exit;
+	}
+
+	/* Iterate over the values for setting */
+	while (len) {
+		u32 offset, mask, value, cur_value;
+		u8 buf[4];
+
+		value = *((u32 *)*data);
+		*data += 4;
+		mask = *((u32 *)*data);
+		*data += 4;
+		offset = *((u32 *)*data);
+		*data += 4;
+
+		rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf,
+				      4);
+		if (rc) {
+			DP_ERR(cdev, "Failed reading from %08x\n",
+			       nvm_image.start_addr + offset);
+			goto exit;
+		}
+
+		cur_value = le32_to_cpu(*((__le32 *)buf));
+		DP_VERBOSE(cdev, NETIF_MSG_DRV,
+			   "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n",
+			   nvm_image.start_addr + offset, cur_value,
+			   (cur_value & ~mask) | (value & mask), value, mask);
+		value = (value & mask) | (cur_value & ~mask);
+		rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
+				       nvm_image.start_addr + offset,
+				       (u8 *)&value, 4);
+		if (rc) {
+			DP_ERR(cdev, "Failed writing to %08x\n",
+			       nvm_image.start_addr + offset);
+			goto exit;
+		}
+
+		len--;
+	}
+exit:
+	return rc;
+}
+
+/* Binary file format -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x3 [command index]                            |
+ * 4B  | b'0: check_response?   | b'1-127  reserved                           |
+ * 8B  | File-type |                   reserved                               |
+ *     \----------------------------------------------------------------------/
+ *     Start a new file of the provided type
+ */
+static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
+					  const u8 **data, bool *check_resp)
+{
+	int rc;
+
+	*data += 4;
+	*check_resp = !!(**data);
+	*data += 4;
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "About to start a new file of type %02x\n", **data);
+	rc = qed_mcp_nvm_put_file_begin(cdev, **data);
+	*data += 4;
+
+	return rc;
+}
+
+/* Binary file format -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x2 [command index]                            |
+ * 4B  |                       Length in bytes                                |
+ * 8B  | b'0: check_response?   | b'1-127  reserved                           |
+ * 12B |                       Offset in bytes                                |
+ * 16B |                       Data ...                                       |
+ *     \----------------------------------------------------------------------/
+ *     Write data as part of a file that was previously started. Data should be
+ *     of length equal to that provided in the message
+ */
+static int qed_nvm_flash_image_file_data(struct qed_dev *cdev,
+					 const u8 **data, bool *check_resp)
+{
+	u32 offset, len;
+	int rc;
+
+	*data += 4;
+	len = *((u32 *)(*data));
+	*data += 4;
+	*check_resp = !!(**data);
+	*data += 4;
+	offset = *((u32 *)(*data));
+	*data += 4;
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "About to write File-data: %08x bytes to offset %08x\n",
+		   len, offset);
+
+	rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset,
+			       (char *)(*data), len);
+	*data += len;
+
+	return rc;
+}
+
+/* Binary file format [General header] -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x12435687 [signature]                         |
+ * 4B  |                       Length in bytes                                |
+ * 8B  | Highest command in this batchfile |          Reserved                |
+ *     \----------------------------------------------------------------------/
+ */
+static int qed_nvm_flash_image_validate(struct qed_dev *cdev,
+					const struct firmware *image,
+					const u8 **data)
+{
+	u32 signature, len;
+
+	/* Check minimum size */
+	if (image->size < 12) {
+		DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size);
+		return -EINVAL;
+	}
+
+	/* Check signature */
+	signature = *((u32 *)(*data));
+	if (signature != 0x12435687) {
+		DP_ERR(cdev, "Wrong signature '%08x'\n", signature);
+		return -EINVAL;
+	}
+
+	*data += 4;
+	/* Validate internal size equals the image-size */
+	len = *((u32 *)(*data));
+	if (len != image->size) {
+		DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n",
+		       len, (u32)image->size);
+		return -EINVAL;
+	}
+
+	*data += 4;
+	/* Make sure driver familiar with all commands necessary for this */
+	if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) {
+		DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n",
+		       *((u16 *)(*data)));
+		return -EINVAL;
+	}
+
+	*data += 4;
+
+	return 0;
+}
+
+static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
+{
+	const struct firmware *image;
+	const u8 *data, *data_end;
+	u32 cmd_type;
+	int rc;
+
+	rc = request_firmware(&image, name, &cdev->pdev->dev);
+	if (rc) {
+		DP_ERR(cdev, "Failed to find '%s'\n", name);
+		return rc;
+	}
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "Flashing '%s' - firmware's data at %p, size is %08x\n",
+		   name, image->data, (u32)image->size);
+	data = image->data;
+	data_end = data + image->size;
+
+	rc = qed_nvm_flash_image_validate(cdev, image, &data);
+	if (rc)
+		goto exit;
+
+	while (data < data_end) {
+		bool check_resp = false;
+
+		/* Parse the actual command */
+		cmd_type = *((u32 *)data);
+		switch (cmd_type) {
+		case QED_NVM_FLASH_CMD_FILE_DATA:
+			rc = qed_nvm_flash_image_file_data(cdev, &data,
+							   &check_resp);
+			break;
+		case QED_NVM_FLASH_CMD_FILE_START:
+			rc = qed_nvm_flash_image_file_start(cdev, &data,
+							    &check_resp);
+			break;
+		case QED_NVM_FLASH_CMD_NVM_CHANGE:
+			rc = qed_nvm_flash_image_access(cdev, &data,
+							&check_resp);
+			break;
+		default:
+			DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
+			rc = -EINVAL;
+			break;
+		}
+
+		if (rc) {
+			DP_ERR(cdev, "Command %08x failed\n", cmd_type);
+			goto exit;
+		}
+
+		/* Check response if needed */
+		if (check_resp) {
+			u32 mcp_response = 0;
+
+			if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) {
+				DP_ERR(cdev, "Failed getting MCP response\n");
+				rc = -EINVAL;
+				goto exit;
+			}
+
+			switch (mcp_response & FW_MSG_CODE_MASK) {
+			case FW_MSG_CODE_OK:
+			case FW_MSG_CODE_NVM_OK:
+			case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK:
+			case FW_MSG_CODE_PHY_OK:
+				break;
+			default:
+				DP_ERR(cdev, "MFW returns error: %08x\n",
+				       mcp_response);
+				rc = -EINVAL;
+				goto exit;
+			}
+		}
+	}
+
+exit:
+	release_firmware(image);
+
+	return rc;
+}
+
 static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
 			     u8 *buf, u16 len)
 {
@@ -1719,6 +2056,7 @@ static int qed_update_mtu(struct qed_dev *cdev, u16 mtu)
 	.dbg_all_data_size = &qed_dbg_all_data_size,
 	.chain_alloc = &qed_chain_alloc,
 	.chain_free = &qed_chain_free,
+	.nvm_flash = &qed_nvm_flash,
 	.nvm_get_image = &qed_nvm_get_image,
 	.set_coalesce = &qed_set_coalesce,
 	.set_led = &qed_set_led,
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 15e398c..ab4e48d 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -483,6 +483,13 @@ struct qed_int_info {
 	u8			used_cnt;
 };
 
+enum qed_nvm_flash_cmd {
+	QED_NVM_FLASH_CMD_FILE_DATA = 0x2,
+	QED_NVM_FLASH_CMD_FILE_START = 0x3,
+	QED_NVM_FLASH_CMD_NVM_CHANGE = 0x4,
+	QED_NVM_FLASH_CMD_NVM_MAX,
+};
+
 struct qed_common_cb_ops {
 	void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc);
 	void	(*link_update)(void			*dev,
@@ -658,6 +665,16 @@ struct qed_common_ops {
 				      struct qed_chain *p_chain);
 
 /**
+ * @brief nvm_flash - Flash nvm data.
+ *
+ * @param cdev
+ * @param name - file containing the data
+ *
+ * @return 0 on success, error otherwise.
+ */
+	int (*nvm_flash)(struct qed_dev *cdev, const char *name);
+
+/**
  * @brief nvm_get_image - reads an entire image from nvram
  *
  * @param cdev
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net-next 4/4] qede: Ethtool flash update support.
  2018-03-26 10:13 [PATCH net-next 0/4] qed*: Flash upgrade support Sudarsana Reddy Kalluru
                   ` (2 preceding siblings ...)
  2018-03-26 10:13 ` [PATCH net-next 3/4] qed: Adapter flash update support Sudarsana Reddy Kalluru
@ 2018-03-26 10:13 ` Sudarsana Reddy Kalluru
  3 siblings, 0 replies; 8+ messages in thread
From: Sudarsana Reddy Kalluru @ 2018-03-26 10:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior

The patch adds ethtool callback implementation for flash update.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
---
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 4ca3847..ecbf1de 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -699,6 +699,14 @@ static u32 qede_get_link(struct net_device *dev)
 	return current_link.link_up;
 }
 
+static int qede_flash_device(struct net_device *dev,
+			     struct ethtool_flash *flash)
+{
+	struct qede_dev *edev = netdev_priv(dev);
+
+	return edev->ops->common->nvm_flash(edev->cdev, flash->data);
+}
+
 static int qede_get_coalesce(struct net_device *dev,
 			     struct ethtool_coalesce *coal)
 {
@@ -1806,6 +1814,7 @@ static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
 
 	.get_tunable = qede_get_tunable,
 	.set_tunable = qede_set_tunable,
+	.flash_device = qede_flash_device,
 };
 
 static const struct ethtool_ops qede_vf_ethtool_ops = {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 1/4] qed: Populate nvm image attribute shadow.
  2018-03-26 10:13 ` [PATCH net-next 1/4] qed: Populate nvm image attribute shadow Sudarsana Reddy Kalluru
@ 2018-03-27 13:01   ` Yuval Mintz
  0 siblings, 0 replies; 8+ messages in thread
From: Yuval Mintz @ 2018-03-27 13:01 UTC (permalink / raw)
  To: Sudarsana Reddy Kalluru; +Cc: davem, netdev, Ariel.Elior

On Mon, Mar 26, 2018 at 03:13:45AM -0700, Sudarsana Reddy Kalluru wrote:
> This patch add support for populating the flash image attributes.
s/add/adds/

[...]

> -int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
> -					struct qed_ptt *p_ptt,
> -					struct bist_nvm_image_att *p_image_att,
> +int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn,
> +				   struct qed_ptt *p_ptt,
> +				   struct bist_nvm_image_att *p_image_att,
>  					u32 image_index)

Indentation seems broken.

>  
> +int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn)
> +{
> +	struct qed_nvm_image_info *nvm_info = &p_hwfn->nvm_info;
> +	struct qed_ptt *p_ptt;
> +	int rc;
> +	u32 i;
> +
> +	p_ptt = qed_ptt_acquire(p_hwfn);
> +	if (!p_ptt) {
> +		DP_ERR(p_hwfn, "failed to acquire ptt\n");
> +		return -EBUSY;
> +	}
> +
> +	/* Acquire from MFW the amount of available images */
> +	nvm_info->num_images = 0;
> +	rc = qed_mcp_bist_nvm_get_num_images(p_hwfn,
> +					     p_ptt, &nvm_info->num_images);
> +	if (rc == -EOPNOTSUPP) {
> +		DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
> +		goto out;
> +	} else if ((rc != 0) || (nvm_info->num_images == 0)) {

rc || !nvm_info->num_images

> +		DP_ERR(p_hwfn, "Failed getting number of images\n");
> +		goto err0;
> +	}
> +
> +	nvm_info->image_att =
> +	    kmalloc(nvm_info->num_images * sizeof(struct bist_nvm_image_att),
> +		    GFP_KERNEL);

Indentation can be better than this.

[...]

> --- a/drivers/net/ethernet/qlogic/qed/qed_selftest.c
> +++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
> @@ -125,10 +125,11 @@ int qed_selftest_nvram(struct qed_dev *cdev)
>  	}
>  
>  	/* Acquire from MFW the amount of available images */
> -	rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
> +	rc = qed_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt, &num_images);
>  	if (rc || !num_images) {
>  		DP_ERR(p_hwfn, "Failed getting number of images\n");
> -		return -EINVAL;
> +		rc = -EINVAL;
> +		goto err0;

Well, this one is a bug fix [Failure flow currently leaks a PTT entry].
If you don't want to treat it as one that's fine, but I think it
deserves its own patch in the series.

>  	}
>  
>  	/* Iterate over images and validate CRC */
> @@ -136,8 +137,8 @@ int qed_selftest_nvram(struct qed_dev *cdev)
>  		/* This mailbox returns information about the image required for
>  		 * reading it.
>  		 */
> -		rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
> -							 &image_att, i);
> +		rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
> +						    &image_att, i);
>  		if (rc) {
>  			DP_ERR(p_hwfn,
>  			       "Failed getting image index %d attributes\n",
> -- 
> 1.8.3.1
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 3/4] qed: Adapter flash update support.
  2018-03-26 10:13 ` [PATCH net-next 3/4] qed: Adapter flash update support Sudarsana Reddy Kalluru
@ 2018-03-27 13:36   ` Yuval Mintz
  2018-03-28  6:56     ` Kalluru, Sudarsana
  0 siblings, 1 reply; 8+ messages in thread
From: Yuval Mintz @ 2018-03-27 13:36 UTC (permalink / raw)
  To: Sudarsana Reddy Kalluru; +Cc: davem, netdev, Ariel.Elior

On Mon, Mar 26, 2018 at 03:13:47AM -0700, Sudarsana Reddy Kalluru wrote:
> This patch adds the required driver support for updating the flash or
> non volatile memory of the adapter. At highlevel, flash upgrade comprises
> of reading the flash images from the input file, validating the images and
> writing it to the respective paritions.

s/it/them/

[...]

> + *     /----------------------------------------------------------------------\
> + * 0B  |                       0x4 [command index]                            |
> + * 4B  | image_type     | Options        |  Number of register settings       |
> + * 8B  |                       Value                                          |
> + * 12B |                       Mask                                           |
> + * 16B |                       Offset                                         |
> + *     \----------------------------------------------------------------------/
> + * There can be several Value-Mask-Offset sets as specified by 'Number of...'.
> + * Options - 0'b - Calculate & Update CRC for image
> + */
> +static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
> +				      bool *check_resp)
> +{
> +	struct qed_nvm_image_att nvm_image;
> +	struct qed_hwfn *p_hwfn;
> +	bool is_crc = false;
> +	u32 image_type;
> +	int rc = 0, i;
> +	u16 len;
> +
 +
> +	nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
> +	nvm_image.length = p_hwfn->nvm_info.image_att[i].len;
> +
> +	DP_VERBOSE(cdev, NETIF_MSG_DRV,
> +		   "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n",
> +		   **data, nvm_image.start_addr, image_type,
> +		   nvm_image.start_addr + nvm_image.length - 1);

Looks like 3rd and 4th printed parameters are flipped.


> +	(*data)++;
> +	is_crc = !!(**data);

If you'd actually want to be able to use the reserved bits
[forward-compatibility] in the future, you should check bit 0 instead of
checking the byte.

> +	(*data)++;
> +	len = *((u16 *)*data);
> +	*data += 2;

[...]

> +
> +/* Binary file format -
> + *     /----------------------------------------------------------------------\
> + * 0B  |                       0x3 [command index]                            |
> + * 4B  | b'0: check_response?   | b'1-127  reserved                           |
This shows there are 128 bits in a 4 byte field.

> + * 8B  | File-type |                   reserved                               |
> + *     \----------------------------------------------------------------------/
> + *     Start a new file of the provided type
> + */
> +static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
> +					  const u8 **data, bool *check_resp)
> +{
> +	int rc;
> +
> +	*data += 4;
> +	*check_resp = !!(**data);

Like above

> +	*data += 4;
> +
> +	DP_VERBOSE(cdev, NETIF_MSG_DRV,
> +		   "About to start a new file of type %02x\n", **data);
> +	rc = qed_mcp_nvm_put_file_begin(cdev, **data);
> +	*data += 4;
> +
> +	return rc;
> +}
> +
> +/* Binary file format -
> + *     /----------------------------------------------------------------------\
> + * 0B  |                       0x2 [command index]                            |
> + * 4B  |                       Length in bytes                                |
> + * 8B  | b'0: check_response?   | b'1-127  reserved                           |

Same as above

> + * 12B |                       Offset in bytes                                |
> + * 16B |                       Data ...                                       |
> + *     \----------------------------------------------------------------------/
> + *     Write data as part of a file that was previously started. Data should be
> + *     of length equal to that provided in the message
> + */
> +static int qed_nvm_flash_image_file_data(struct qed_dev *cdev,
> +					 const u8 **data, bool *check_resp)
> +{
> +	u32 offset, len;
> +	int rc;
> +
> +	*data += 4;
> +	len = *((u32 *)(*data));
> +	*data += 4;
> +	*check_resp = !!(**data);

Same as above

> +	*data += 4;
> +	offset = *((u32 *)(*data));
> +	*data += 4;
> +
> +	DP_VERBOSE(cdev, NETIF_MSG_DRV,
> +		   "About to write File-data: %08x bytes to offset %08x\n",
> +		   len, offset);
> +
> +	rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset,
> +			       (char *)(*data), len);
> +	*data += len;
> +
> +	return rc;
> +}

[...]

> +
> +static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
> +{
> +	rc = qed_nvm_flash_image_validate(cdev, image, &data);
> +	if (rc)
> +		goto exit;
> +
> +	while (data < data_end) {
> +		bool check_resp = false;
> +
> +		/* Parse the actual command */
> +		cmd_type = *((u32 *)data);

What's the final format of the file? Is it LE?

> +		switch (cmd_type) {
> +		case QED_NVM_FLASH_CMD_FILE_DATA:
> +			rc = qed_nvm_flash_image_file_data(cdev, &data,
> +							   &check_resp);
> +			break;
> +		case QED_NVM_FLASH_CMD_FILE_START:
> +			rc = qed_nvm_flash_image_file_start(cdev, &data,
> +							    &check_resp);
> +			break;
> +		case QED_NVM_FLASH_CMD_NVM_CHANGE:
> +			rc = qed_nvm_flash_image_access(cdev, &data,
> +							&check_resp);
> +			break;
> +		default:
> +			DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
> +			rc = -EINVAL;
> +			break;

Either goto or drop the print; You're getting from the next condition.

> +		}
> +
> +		if (rc) {
> +			DP_ERR(cdev, "Command %08x failed\n", cmd_type);
> +			goto exit;
> +		}
> +
> +		/* Check response if needed */
> +		if (check_resp) {
> +			u32 mcp_response = 0;
> +
> +			if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) {
> +				DP_ERR(cdev, "Failed getting MCP response\n");
> +				rc = -EINVAL;
> +				goto exit;
> +			}
> +
> +			switch (mcp_response & FW_MSG_CODE_MASK) {
> +			case FW_MSG_CODE_OK:
> +			case FW_MSG_CODE_NVM_OK:
> +			case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK:
> +			case FW_MSG_CODE_PHY_OK:
> +				break;
> +			default:
> +				DP_ERR(cdev, "MFW returns error: %08x\n",
> +				       mcp_response);
> +				rc = -EINVAL;
> +				goto exit;
> +			}
> +		}
> +	}
> +
> +exit:
> +	release_firmware(image);
> +
> +	return rc;
> +}
> +
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH net-next 3/4] qed: Adapter flash update support.
  2018-03-27 13:36   ` Yuval Mintz
@ 2018-03-28  6:56     ` Kalluru, Sudarsana
  0 siblings, 0 replies; 8+ messages in thread
From: Kalluru, Sudarsana @ 2018-03-28  6:56 UTC (permalink / raw)
  To: Yuval Mintz; +Cc: davem, netdev, Elior, Ariel



-----Original Message-----
From: Yuval Mintz [mailto:yuvalm@mellanox.com] 
Sent: 27 March 2018 19:07
To: Kalluru, Sudarsana <Sudarsana.Kalluru@cavium.com>
Cc: davem@davemloft.net; netdev@vger.kernel.org; Elior, Ariel <Ariel.Elior@cavium.com>
Subject: Re: [PATCH net-next 3/4] qed: Adapter flash update support.

On Mon, Mar 26, 2018 at 03:13:47AM -0700, Sudarsana Reddy Kalluru wrote:
> This patch adds the required driver support for updating the flash or 
> non volatile memory of the adapter. At highlevel, flash upgrade 
> comprises of reading the flash images from the input file, validating 
> the images and writing it to the respective paritions.

s/it/them/

[...]

> + *     /----------------------------------------------------------------------\
> + * 0B  |                       0x4 [command index]                            |
> + * 4B  | image_type     | Options        |  Number of register settings       |
> + * 8B  |                       Value                                          |
> + * 12B |                       Mask                                           |
> + * 16B |                       Offset                                         |
> + *     \----------------------------------------------------------------------/
> + * There can be several Value-Mask-Offset sets as specified by 'Number of...'.
> + * Options - 0'b - Calculate & Update CRC for image  */ static int 
> +qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
> +				      bool *check_resp)
> +{
> +	struct qed_nvm_image_att nvm_image;
> +	struct qed_hwfn *p_hwfn;
> +	bool is_crc = false;
> +	u32 image_type;
> +	int rc = 0, i;
> +	u16 len;
> +
 +
> +	nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
> +	nvm_image.length = p_hwfn->nvm_info.image_att[i].len;
> +
> +	DP_VERBOSE(cdev, NETIF_MSG_DRV,
> +		   "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n",
> +		   **data, nvm_image.start_addr, image_type,
> +		   nvm_image.start_addr + nvm_image.length - 1);

Looks like 3rd and 4th printed parameters are flipped.


> +	(*data)++;
> +	is_crc = !!(**data);

If you'd actually want to be able to use the reserved bits [forward-compatibility] in the future, you should check bit 0 instead of checking the byte.

> +	(*data)++;
> +	len = *((u16 *)*data);
> +	*data += 2;

[...]

> +
> +/* Binary file format -
> + *     /----------------------------------------------------------------------\
> + * 0B  |                       0x3 [command index]                            |
> + * 4B  | b'0: check_response?   | b'1-127  reserved                           |
This shows there are 128 bits in a 4 byte field.

> + * 8B  | File-type |                   reserved                               |
> + *     \----------------------------------------------------------------------/
> + *     Start a new file of the provided type
> + */
> +static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
> +					  const u8 **data, bool *check_resp) {
> +	int rc;
> +
> +	*data += 4;
> +	*check_resp = !!(**data);

Like above

> +	*data += 4;
> +
> +	DP_VERBOSE(cdev, NETIF_MSG_DRV,
> +		   "About to start a new file of type %02x\n", **data);
> +	rc = qed_mcp_nvm_put_file_begin(cdev, **data);
> +	*data += 4;
> +
> +	return rc;
> +}
> +
> +/* Binary file format -
> + *     /----------------------------------------------------------------------\
> + * 0B  |                       0x2 [command index]                            |
> + * 4B  |                       Length in bytes                                |
> + * 8B  | b'0: check_response?   | b'1-127  reserved                           |

Same as above

> + * 12B |                       Offset in bytes                                |
> + * 16B |                       Data ...                                       |
> + *     \----------------------------------------------------------------------/
> + *     Write data as part of a file that was previously started. Data should be
> + *     of length equal to that provided in the message
> + */
> +static int qed_nvm_flash_image_file_data(struct qed_dev *cdev,
> +					 const u8 **data, bool *check_resp) {
> +	u32 offset, len;
> +	int rc;
> +
> +	*data += 4;
> +	len = *((u32 *)(*data));
> +	*data += 4;
> +	*check_resp = !!(**data);

Same as above

> +	*data += 4;
> +	offset = *((u32 *)(*data));
> +	*data += 4;
> +
> +	DP_VERBOSE(cdev, NETIF_MSG_DRV,
> +		   "About to write File-data: %08x bytes to offset %08x\n",
> +		   len, offset);
> +
> +	rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset,
> +			       (char *)(*data), len);
> +	*data += len;
> +
> +	return rc;
> +}

[...]

> +
> +static int qed_nvm_flash(struct qed_dev *cdev, const char *name) {
> +	rc = qed_nvm_flash_image_validate(cdev, image, &data);
> +	if (rc)
> +		goto exit;
> +
> +	while (data < data_end) {
> +		bool check_resp = false;
> +
> +		/* Parse the actual command */
> +		cmd_type = *((u32 *)data);

What's the final format of the file? Is it LE?

<Sudarsana>   The file contents are in LE format. Thanks for the detailed review. Will re-submit the patch series with the review comments incorporated.

> +		switch (cmd_type) {
> +		case QED_NVM_FLASH_CMD_FILE_DATA:
> +			rc = qed_nvm_flash_image_file_data(cdev, &data,
> +							   &check_resp);
> +			break;
> +		case QED_NVM_FLASH_CMD_FILE_START:
> +			rc = qed_nvm_flash_image_file_start(cdev, &data,
> +							    &check_resp);
> +			break;
> +		case QED_NVM_FLASH_CMD_NVM_CHANGE:
> +			rc = qed_nvm_flash_image_access(cdev, &data,
> +							&check_resp);
> +			break;
> +		default:
> +			DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
> +			rc = -EINVAL;
> +			break;

Either goto or drop the print; You're getting from the next condition.

> +		}
> +
> +		if (rc) {
> +			DP_ERR(cdev, "Command %08x failed\n", cmd_type);
> +			goto exit;
> +		}
> +
> +		/* Check response if needed */
> +		if (check_resp) {
> +			u32 mcp_response = 0;
> +
> +			if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) {
> +				DP_ERR(cdev, "Failed getting MCP response\n");
> +				rc = -EINVAL;
> +				goto exit;
> +			}
> +
> +			switch (mcp_response & FW_MSG_CODE_MASK) {
> +			case FW_MSG_CODE_OK:
> +			case FW_MSG_CODE_NVM_OK:
> +			case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK:
> +			case FW_MSG_CODE_PHY_OK:
> +				break;
> +			default:
> +				DP_ERR(cdev, "MFW returns error: %08x\n",
> +				       mcp_response);
> +				rc = -EINVAL;
> +				goto exit;
> +			}
> +		}
> +	}
> +
> +exit:
> +	release_firmware(image);
> +
> +	return rc;
> +}
> +
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-03-28  6:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-26 10:13 [PATCH net-next 0/4] qed*: Flash upgrade support Sudarsana Reddy Kalluru
2018-03-26 10:13 ` [PATCH net-next 1/4] qed: Populate nvm image attribute shadow Sudarsana Reddy Kalluru
2018-03-27 13:01   ` Yuval Mintz
2018-03-26 10:13 ` [PATCH net-next 2/4] qed: Add APIs for flash access Sudarsana Reddy Kalluru
2018-03-26 10:13 ` [PATCH net-next 3/4] qed: Adapter flash update support Sudarsana Reddy Kalluru
2018-03-27 13:36   ` Yuval Mintz
2018-03-28  6:56     ` Kalluru, Sudarsana
2018-03-26 10:13 ` [PATCH net-next 4/4] qede: Ethtool " Sudarsana Reddy Kalluru

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.