[v6,7/8] net/rnp add devargs runtime parsing functions

Message ID 20230901023050.40893-8-caowenbo@mucse.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series drivers/net Add Support mucse N10 Pmd Driver |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

11 Sept. 1, 2023, 2:30 a.m. UTC
  add various runtime devargs command line options
supported by this driver.

Signed-off-by: Wenbo Cao <caowenbo@mucse.com>
---
 drivers/net/rnp/rnp.h        |  22 +++++
 drivers/net/rnp/rnp_ethdev.c | 166 +++++++++++++++++++++++++++++++++++
 drivers/net/rnp/rnp_mbx_fw.c | 164 ++++++++++++++++++++++++++++++++++
 drivers/net/rnp/rnp_mbx_fw.h |  69 +++++++++++++++
 4 files changed, 421 insertions(+)
  

Comments

Ferruh Yigit Sept. 5, 2023, 3:46 p.m. UTC | #1
Addressed
On 9/1/2023 3:30 AM, Wenbo Cao wrote:
> add various runtime devargs command line options
> supported by this driver.
> 
> Signed-off-by: Wenbo Cao <caowenbo@mucse.com>

<...>

>  
> +#define RNP_HW_MAC_LOOPBACK_ARG      "hw_loopback"
> +#define RNP_FW_UPDATE                "fw_update"
> +#define RNP_RX_FUNC_SELECT           "rx_func_sec"
> +#define RNP_TX_FUNC_SELECT           "tx_func_sec"
> +#define RNP_FW_4X10G_10G_1G_DET      "fw_4x10g_10g_1g_auto_det"
> +#define RNP_FW_FORCE_SPEED_1G        "fw_force_1g_speed"
> +

Please document these runtime arguments in the device document.

Also please add 'RTE_PMD_REGISTER_PARAM_STRING()' macros to document
argument for pmdinfogen, please see samples in existing code.

<...>

> +
> +static int
> +rnp_parse_io_select_func(const char *key, const char *value, void *extra_args)
> +{
> +	uint8_t select = RNP_IO_FUNC_USE_NONE;
> +
> +	RTE_SET_USED(key);
> +
> +	if (strcmp(value, "vec") == 0)
> +		select = RNP_IO_FUNC_USE_VEC;
> +	else if (strcmp(value, "simple") == 0)
> +		select = RNP_IO_FUNC_USE_SIMPLE;
> +	else if (strcmp(value, "common") == 0)
> +		select = RNP_IO_FUNC_USE_COMMON;
> +

There is already an generic eal argument that lets you select between
vector and scalar datapath implementation:
--force-max-simd-bitwidth=<val>

<...>

> +static int rnp_post_handle(struct rnp_eth_adapter *adapter)
> +{
> +	bool on = false;
> +
> +	if (!adapter->eth_dev)
> +		return -ENOMEM;
> +	if (adapter->do_fw_update && adapter->fw_path) {
> +		rnp_fw_update(adapter);
> +		adapter->do_fw_update = 0;

This patch also enables FW upgrade, can you please detail this in the
commit log? Or even you can consider to split this part into separate patch.
  
11 Sept. 6, 2023, 9:13 a.m. UTC | #2
Unaddressed
> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: 2023年9月5日 23:47
> To: Wenbo Cao <caowenbo@mucse.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; andrew.rybchenko@oktetlabs.ru;
> yaojun@mucse.com
> Subject: Re: [PATCH v6 7/8] net/rnp add devargs runtime parsing functions
> 
> On 9/1/2023 3:30 AM, Wenbo Cao wrote:
> > add various runtime devargs command line options supported by this
> > driver.
> >
> > Signed-off-by: Wenbo Cao <caowenbo@mucse.com>
> 
> <...>
> 
> >
> > +#define RNP_HW_MAC_LOOPBACK_ARG      "hw_loopback"
> > +#define RNP_FW_UPDATE                "fw_update"
> > +#define RNP_RX_FUNC_SELECT           "rx_func_sec"
> > +#define RNP_TX_FUNC_SELECT           "tx_func_sec"
> > +#define RNP_FW_4X10G_10G_1G_DET      "fw_4x10g_10g_1g_auto_det"
> > +#define RNP_FW_FORCE_SPEED_1G        "fw_force_1g_speed"
> > +
> 
> Please document these runtime arguments in the device document.
> 
> Also please add 'RTE_PMD_REGISTER_PARAM_STRING()' macros to document
> argument for pmdinfogen, please see samples in existing code.
> 
> <...>
> 
OK, I will check the samples.
> > +
> > +static int
> > +rnp_parse_io_select_func(const char *key, const char *value, void
> > +*extra_args) {
> > +	uint8_t select = RNP_IO_FUNC_USE_NONE;
> > +
> > +	RTE_SET_USED(key);
> > +
> > +	if (strcmp(value, "vec") == 0)
> > +		select = RNP_IO_FUNC_USE_VEC;
> > +	else if (strcmp(value, "simple") == 0)
> > +		select = RNP_IO_FUNC_USE_SIMPLE;
> > +	else if (strcmp(value, "common") == 0)
> > +		select = RNP_IO_FUNC_USE_COMMON;
> > +
> 
> There is already an generic eal argument that lets you select between vector and
> scalar datapath implementation:
> --force-max-simd-bitwidth=<val>
> 
> <...>
> 
> --force-max-simd-bitwidth=<val>
This option I have noticed before. Thanks a lot.
I will check the generic eal argume code, and reedit the interrelated code
> > +static int rnp_post_handle(struct rnp_eth_adapter *adapter) {
> > +	bool on = false;
> > +
> > +	if (!adapter->eth_dev)
> > +		return -ENOMEM;
> > +	if (adapter->do_fw_update && adapter->fw_path) {
> > +		rnp_fw_update(adapter);
> > +		adapter->do_fw_update = 0;
> 
> This patch also enables FW upgrade, can you please detail this in the commit log?
> Or even you can consider to split this part into separate patch.
> 
> 
> 
For this, I will split it to another commit.
  

Patch

diff --git a/drivers/net/rnp/rnp.h b/drivers/net/rnp/rnp.h
index 9ae801414b..7e797cf177 100644
--- a/drivers/net/rnp/rnp.h
+++ b/drivers/net/rnp/rnp.h
@@ -107,6 +107,8 @@  struct rnp_eth_port {
 	struct rnp_eth_adapter *adapt;
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
 	struct rnp_hw *hw;
+	uint8_t rx_func_sec; /* force set io rx_func */
+	uint8_t tx_func_sec; /* force set io tx func */
 	struct rte_eth_dev *eth_dev;
 	struct rnp_port_attr attr;
 	/* Recvice Mac Address Record Table */
@@ -122,6 +124,13 @@  struct rnp_share_ops {
 	const struct rnp_mac_api *mac_api;
 } __rte_cache_aligned;
 
+enum {
+	RNP_IO_FUNC_USE_NONE = 0,
+	RNP_IO_FUNC_USE_VEC,
+	RNP_IO_FUNC_USE_SIMPLE,
+	RNP_IO_FUNC_USE_COMMON,
+};
+
 struct rnp_eth_adapter {
 	enum rnp_work_mode mode;
 	enum rnp_resource_share_m s_mode; /* Port Resource Share Policy */
@@ -135,6 +144,19 @@  struct rnp_eth_adapter {
 	int max_link_speed;
 	uint8_t num_ports; /* Cur Pf Has physical Port Num */
 	uint8_t lane_mask;
+
+	uint8_t rx_func_sec; /* force set io rx_func */
+	uint8_t tx_func_sec; /* force set io tx func*/
+	/*fw-update*/
+	bool  do_fw_update;
+	char *fw_path;
+
+	bool loopback_en;
+	bool fw_sfp_10g_1g_auto_det;
+	int fw_force_speed_1g;
+#define FOCE_SPEED_1G_NOT_SET	(-1)
+#define FOCE_SPEED_1G_DISABLED	(0)
+#define FOCE_SPEED_1G_ENABLED	(1)
 } __rte_cache_aligned;
 
 #define RNP_DEV_TO_PORT(eth_dev) \
diff --git a/drivers/net/rnp/rnp_ethdev.c b/drivers/net/rnp/rnp_ethdev.c
index f0ef2ef329..131da42259 100644
--- a/drivers/net/rnp/rnp_ethdev.c
+++ b/drivers/net/rnp/rnp_ethdev.c
@@ -6,6 +6,7 @@ 
 #include <rte_io.h>
 #include <rte_malloc.h>
 #include <ethdev_driver.h>
+#include <rte_kvargs.h>
 
 #include "rnp.h"
 #include "rnp_api.h"
@@ -14,6 +15,13 @@ 
 #include "rnp_rxtx.h"
 #include "rnp_logs.h"
 
+#define RNP_HW_MAC_LOOPBACK_ARG      "hw_loopback"
+#define RNP_FW_UPDATE                "fw_update"
+#define RNP_RX_FUNC_SELECT           "rx_func_sec"
+#define RNP_TX_FUNC_SELECT           "tx_func_sec"
+#define RNP_FW_4X10G_10G_1G_DET      "fw_4x10g_10g_1g_auto_det"
+#define RNP_FW_FORCE_SPEED_1G        "fw_force_1g_speed"
+
 static int
 rnp_mac_rx_disable(struct rte_eth_dev *dev)
 {
@@ -108,6 +116,8 @@  rnp_init_port_resource(struct rnp_eth_adapter *adapter,
 	struct rnp_hw *hw = &adapter->hw;
 
 	port->adapt = adapter;
+	port->rx_func_sec = adapter->rx_func_sec;
+	port->tx_func_sec = adapter->tx_func_sec;
 	port->s_mode = adapter->s_mode;
 	port->port_stopped = 1;
 	port->hw = hw;
@@ -443,6 +453,154 @@  rnp_special_ops_init(struct rte_eth_dev *eth_dev)
 	return 0;
 }
 
+static const char *const rnp_valid_arguments[] = {
+	RNP_HW_MAC_LOOPBACK_ARG,
+	RNP_FW_UPDATE,
+	RNP_RX_FUNC_SELECT,
+	RNP_TX_FUNC_SELECT,
+	RNP_FW_4X10G_10G_1G_DET,
+	RNP_FW_FORCE_SPEED_1G,
+	NULL
+};
+
+static int
+rnp_parse_handle_devarg(const char *key, const char *value,
+			void *extra_args)
+{
+	struct rnp_eth_adapter *adapter = NULL;
+
+	if (value == NULL || extra_args == NULL)
+		return -EINVAL;
+
+	if (strcmp(key, RNP_HW_MAC_LOOPBACK_ARG) == 0) {
+		uint64_t *n = extra_args;
+		*n = (uint16_t)strtoul(value, NULL, 10);
+		if (*n > UINT16_MAX && errno == ERANGE) {
+			RNP_PMD_DRV_LOG(ERR, "invalid extra param value\n");
+			return -1;
+		}
+	} else if (strcmp(key, RNP_FW_UPDATE) == 0) {
+		adapter = (struct rnp_eth_adapter *)extra_args;
+		adapter->do_fw_update = true;
+		adapter->fw_path = strdup(value);
+	} else if (strcmp(key, RNP_FW_4X10G_10G_1G_DET) == 0) {
+		adapter = (struct rnp_eth_adapter *)extra_args;
+		if (adapter->num_ports == 2 && adapter->hw.speed == 10 * 1000) {
+			adapter->fw_sfp_10g_1g_auto_det =
+				(strcmp(value, "on") == 0) ? true : false;
+		} else {
+			adapter->fw_sfp_10g_1g_auto_det = false;
+		}
+	} else if (strcmp(key, RNP_FW_FORCE_SPEED_1G) == 0) {
+		adapter = (struct rnp_eth_adapter *)extra_args;
+		if (adapter->num_ports == 2) {
+			if (strcmp(value, "on") == 0)
+				adapter->fw_force_speed_1g = FOCE_SPEED_1G_ENABLED;
+			else if (strcmp(value, "off") == 0)
+				adapter->fw_force_speed_1g = FOCE_SPEED_1G_DISABLED;
+		}
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+rnp_parse_io_select_func(const char *key, const char *value, void *extra_args)
+{
+	uint8_t select = RNP_IO_FUNC_USE_NONE;
+
+	RTE_SET_USED(key);
+
+	if (strcmp(value, "vec") == 0)
+		select = RNP_IO_FUNC_USE_VEC;
+	else if (strcmp(value, "simple") == 0)
+		select = RNP_IO_FUNC_USE_SIMPLE;
+	else if (strcmp(value, "common") == 0)
+		select = RNP_IO_FUNC_USE_COMMON;
+
+	*(uint8_t *)extra_args = select;
+
+	return 0;
+}
+
+static int
+rnp_parse_devargs(struct rnp_eth_adapter *adapter,
+		  struct rte_devargs *devargs)
+{
+	uint8_t rx_io_func = RNP_IO_FUNC_USE_NONE;
+	uint8_t tx_io_func = RNP_IO_FUNC_USE_NONE;
+	struct rte_kvargs *kvlist;
+	bool loopback_en = false;
+	int ret = 0;
+
+	adapter->do_fw_update = false;
+	adapter->fw_sfp_10g_1g_auto_det = false;
+	adapter->fw_force_speed_1g = FOCE_SPEED_1G_NOT_SET;
+
+	if (!devargs)
+		goto def;
+
+	kvlist = rte_kvargs_parse(devargs->args, rnp_valid_arguments);
+	if (kvlist == NULL)
+		goto def;
+
+	if (rte_kvargs_count(kvlist, RNP_HW_MAC_LOOPBACK_ARG) == 1)
+		ret = rte_kvargs_process(kvlist, RNP_HW_MAC_LOOPBACK_ARG,
+				&rnp_parse_handle_devarg, &loopback_en);
+
+	if (rte_kvargs_count(kvlist, RNP_FW_4X10G_10G_1G_DET) == 1)
+		ret = rte_kvargs_process(kvlist,
+				RNP_FW_4X10G_10G_1G_DET,
+				&rnp_parse_handle_devarg,
+				adapter);
+
+	if (rte_kvargs_count(kvlist, RNP_FW_FORCE_SPEED_1G) == 1)
+		ret = rte_kvargs_process(kvlist,
+				RNP_FW_FORCE_SPEED_1G,
+				&rnp_parse_handle_devarg,
+				adapter);
+
+	if (rte_kvargs_count(kvlist, RNP_FW_UPDATE) == 1)
+		ret = rte_kvargs_process(kvlist, RNP_FW_UPDATE,
+				&rnp_parse_handle_devarg, adapter);
+	if (rte_kvargs_count(kvlist, RNP_RX_FUNC_SELECT) == 1)
+		ret = rte_kvargs_process(kvlist, RNP_RX_FUNC_SELECT,
+				&rnp_parse_io_select_func, &rx_io_func);
+	if (rte_kvargs_count(kvlist, RNP_TX_FUNC_SELECT) == 1)
+		ret = rte_kvargs_process(kvlist, RNP_TX_FUNC_SELECT,
+				&rnp_parse_io_select_func, &tx_io_func);
+	rte_kvargs_free(kvlist);
+def:
+	adapter->loopback_en = loopback_en;
+	adapter->rx_func_sec = rx_io_func;
+	adapter->tx_func_sec = tx_io_func;
+
+	return ret;
+}
+
+static int rnp_post_handle(struct rnp_eth_adapter *adapter)
+{
+	bool on = false;
+
+	if (!adapter->eth_dev)
+		return -ENOMEM;
+	if (adapter->do_fw_update && adapter->fw_path) {
+		rnp_fw_update(adapter);
+		adapter->do_fw_update = 0;
+	}
+
+	if (adapter->fw_sfp_10g_1g_auto_det)
+		return rnp_hw_set_fw_10g_1g_auto_detch(adapter->eth_dev, 1);
+
+	on = (adapter->fw_force_speed_1g == FOCE_SPEED_1G_ENABLED) ? 1 : 0;
+	if (adapter->fw_force_speed_1g != FOCE_SPEED_1G_NOT_SET)
+		return rnp_hw_set_fw_force_speed_1g(adapter->eth_dev, on);
+
+	return 0;
+}
+
 static int
 rnp_eth_dev_init(struct rte_eth_dev *dev)
 {
@@ -492,6 +650,11 @@  rnp_eth_dev_init(struct rte_eth_dev *dev)
 	/* We need Use Device Id To Change The Resource Mode */
 	rnp_special_ops_init(dev);
 	port->hw = hw;
+	ret = rnp_parse_devargs(adapter, pci_dev->device.devargs);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "parse_devargs failed");
+		return ret;
+	}
 	for (p_id = 0; p_id < adapter->num_ports; p_id++) {
 		/* port 0 resource has been allocated When Probe */
 		if (!p_id) {
@@ -517,6 +680,9 @@  rnp_eth_dev_init(struct rte_eth_dev *dev)
 		rnp_mac_rx_disable(eth_dev);
 		rnp_mac_tx_disable(eth_dev);
 	}
+	ret = rnp_post_handle(adapter);
+	if (ret)
+		goto eth_alloc_error;
 
 	return 0;
 eth_alloc_error:
diff --git a/drivers/net/rnp/rnp_mbx_fw.c b/drivers/net/rnp/rnp_mbx_fw.c
index 856b3f956b..0c3f499cf2 100644
--- a/drivers/net/rnp/rnp_mbx_fw.c
+++ b/drivers/net/rnp/rnp_mbx_fw.c
@@ -105,6 +105,27 @@  static int rnp_mbx_fw_post_req(struct rte_eth_dev *dev,
 	return err;
 }
 
+static int
+rnp_mbx_write_posted_locked(struct rte_eth_dev *dev, struct mbx_fw_cmd_req *req)
+{
+	const struct rnp_mbx_api *ops = RNP_DEV_TO_MBX_OPS(dev);
+	struct rnp_hw *hw = RNP_DEV_TO_HW(dev);
+	int err = 0;
+
+	rte_spinlock_lock(&hw->fw_lock);
+
+	err = ops->write_posted(dev, (u32 *)req,
+			(req->datalen + MBX_REQ_HDR_LEN) / 4, MBX_FW);
+	if (err) {
+		RNP_PMD_LOG(ERR, "%s failed!\n", __func__);
+		goto quit;
+	}
+
+quit:
+	rte_spinlock_unlock(&hw->fw_lock);
+	return err;
+}
+
 static int rnp_fw_get_capablity(struct rte_eth_dev *dev,
 				struct phy_abilities *abil)
 {
@@ -381,3 +402,146 @@  int rnp_mbx_get_lane_stat(struct rte_eth_dev *dev)
 quit:
 	return err;
 }
+
+static int rnp_maintain_req(struct rte_eth_dev *dev,
+		int cmd,
+		int arg0,
+		int req_data_bytes,
+		int reply_bytes,
+		phys_addr_t dma_phy_addr)
+{
+	struct rnp_hw *hw = RNP_DEV_TO_HW(dev);
+	struct mbx_req_cookie *cookie = NULL;
+	struct mbx_fw_cmd_req req;
+	int err;
+
+	if (!hw->mbx.irq_enabled)
+		return -EIO;
+	cookie = rnp_memzone_reserve(hw->cookie_p_name, 0);
+	if (!cookie)
+		return -ENOMEM;
+	memset(&req, 0, sizeof(req));
+	cookie->timeout_ms = 60 * 1000; /* 60s */
+
+	build_maintain_req(&req,
+			cookie,
+			cmd,
+			arg0,
+			req_data_bytes,
+			reply_bytes,
+			dma_phy_addr & 0xffffffff,
+			(dma_phy_addr >> 32) & 0xffffffff);
+
+	err = rnp_mbx_fw_post_req(dev, &req, cookie);
+
+	return (err) ? -EIO : 0;
+}
+
+int rnp_fw_update(struct rnp_eth_adapter *adapter)
+{
+	const struct rte_memzone *rz = NULL;
+	struct maintain_req *mt;
+	FILE *file;
+	int fsz;
+#define MAX_FW_BIN_SZ (552 * 1024)
+#define FW_256KB          (256 * 1024)
+
+	RNP_PMD_LOG(INFO, "%s: %s\n", __func__, adapter->fw_path);
+
+	file = fopen(adapter->fw_path, "rb");
+	if (!file) {
+		RNP_PMD_LOG(ERR,
+				"RNP: [%s] %s can't open for read\n",
+				__func__,
+				adapter->fw_path);
+		return -ENOENT;
+	}
+	/* get dma */
+	rz = rte_memzone_reserve("fw_update", MAX_FW_BIN_SZ, SOCKET_ID_ANY, 4);
+	if (rz == NULL) {
+		RNP_PMD_LOG(ERR, "RNP: [%s] not memory:%d\n", __func__,
+				MAX_FW_BIN_SZ);
+		return -EFBIG;
+	}
+	memset(rz->addr, 0xff, rz->len);
+	mt = (struct maintain_req *)rz->addr;
+
+	/* read data */
+	fsz = fread(mt->data, 1, rz->len, file);
+	if (fsz <= 0) {
+		RNP_PMD_LOG(INFO, "RNP: [%s] read failed! err:%d\n",
+				__func__, fsz);
+		return -EIO;
+	}
+	fclose(file);
+
+	if (fsz > ((256 + 4) * 1024)) {
+		printf("fw length:%d is two big. not supported!\n", fsz);
+		return -EINVAL;
+	}
+	RNP_PMD_LOG(NOTICE, "RNP: fw update ...\n");
+	fflush(stdout);
+
+	/* ==== update fw */
+	mt->magic       = MAINTAIN_MAGIC;
+	mt->cmd         = MT_WRITE_FLASH;
+	mt->arg0        = 1;
+	mt->req_data_bytes = (fsz > FW_256KB) ? FW_256KB : fsz;
+	mt->reply_bytes = 0;
+
+	if (rnp_maintain_req(adapter->eth_dev, mt->cmd, mt->arg0,
+				mt->req_data_bytes, mt->reply_bytes, rz->iova))
+		RNP_PMD_LOG(ERR, "maintain request failed!\n");
+	else
+		RNP_PMD_LOG(INFO, "maintail request done!\n");
+
+	/* ==== update cfg */
+	if (fsz > FW_256KB) {
+		mt->magic       = MAINTAIN_MAGIC;
+		mt->cmd         = MT_WRITE_FLASH;
+		mt->arg0        = 2;
+		mt->req_data_bytes = 4096;
+		mt->reply_bytes    = 0;
+		memcpy(mt->data, mt->data + FW_256KB, mt->req_data_bytes);
+
+		if (rnp_maintain_req(adapter->eth_dev,
+					mt->cmd, mt->arg0, mt->req_data_bytes,
+					mt->reply_bytes, rz->iova))
+			RNP_PMD_LOG(ERR, "maintain request failed!\n");
+		else
+			RNP_PMD_LOG(INFO, "maintail request done!\n");
+	}
+
+	RNP_PMD_LOG(NOTICE, "done\n");
+	fflush(stdout);
+
+	rte_memzone_free(rz);
+
+	exit(0);
+
+	return 0;
+}
+
+static int rnp_mbx_set_dump(struct rte_eth_dev *dev, int flag)
+{
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+	struct mbx_fw_cmd_req req;
+	int err;
+
+	memset(&req, 0, sizeof(req));
+	build_set_dump(&req, port->attr.nr_lane, flag);
+
+	err = rnp_mbx_write_posted_locked(dev, &req);
+
+	return err;
+}
+
+int rnp_hw_set_fw_10g_1g_auto_detch(struct rte_eth_dev *dev, int enable)
+{
+	return rnp_mbx_set_dump(dev, 0x01140000 | (enable & 1));
+}
+
+int rnp_hw_set_fw_force_speed_1g(struct rte_eth_dev *dev, int enable)
+{
+	return rnp_mbx_set_dump(dev, 0x01150000 | (enable & 1));
+}
diff --git a/drivers/net/rnp/rnp_mbx_fw.h b/drivers/net/rnp/rnp_mbx_fw.h
index c4a04a3f09..39fb0f6ef3 100644
--- a/drivers/net/rnp/rnp_mbx_fw.h
+++ b/drivers/net/rnp/rnp_mbx_fw.h
@@ -16,6 +16,17 @@  struct mbx_req_cookie {
 	int priv_len;
 	char priv[RNP_MAX_SHARE_MEM];
 };
+struct maintain_req {
+	int magic;
+#define MAINTAIN_MAGIC 0xa6a7a8a9
+
+	int      cmd;
+	int      arg0;
+	int      req_data_bytes;
+	int      reply_bytes;
+	char data[0];
+} __rte_packed;
+
 enum GENERIC_CMD {
 	/* link configuration admin commands */
 	GET_PHY_ABALITY = 0x0601,
@@ -23,6 +34,9 @@  enum GENERIC_CMD {
 	RESET_PHY = 0x0603,
 	GET_LANE_STATUS = 0x0610,
 	SET_EVENT_MASK = 0x0613,
+	 /* fw update */
+	FW_MAINTAIN = 0x0701,
+	SET_DUMP = 0x0a10,
 };
 
 enum link_event_mask {
@@ -211,6 +225,21 @@  struct mbx_fw_cmd_req {
 		struct {
 			int nr_lane;
 		} get_lane_st;
+
+		struct {
+			int cmd;
+#define MT_WRITE_FLASH 1
+			int arg0;
+			int req_bytes;
+			int reply_bytes;
+			int ddr_lo;
+			int ddr_hi;
+		} maintain;
+
+		struct {
+			int flag;
+			int nr_lane;
+		} set_dump;
 	};
 } __rte_packed __rte_aligned(4);
 
@@ -284,6 +313,43 @@  build_get_lane_status_req(struct mbx_fw_cmd_req *req,
 	req->get_lane_st.nr_lane = nr_lane;
 }
 
+static inline void
+build_maintain_req(struct mbx_fw_cmd_req *req,
+		   void *cookie,
+		   int cmd,
+		   int arg0,
+		   int req_bytes,
+		   int reply_bytes,
+		   u32 dma_phy_lo,
+		   u32 dma_phy_hi)
+{
+	req->flags = 0;
+	req->opcode = FW_MAINTAIN;
+	req->datalen = sizeof(req->maintain);
+	req->cookie = cookie;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->maintain.cmd = cmd;
+	req->maintain.arg0 = arg0;
+	req->maintain.req_bytes = req_bytes;
+	req->maintain.reply_bytes = reply_bytes;
+	req->maintain.ddr_lo = dma_phy_lo;
+	req->maintain.ddr_hi = dma_phy_hi;
+}
+
+static inline void
+build_set_dump(struct mbx_fw_cmd_req *req, int nr_lane, int flag)
+{
+	req->flags = 0;
+	req->opcode = SET_DUMP;
+	req->datalen = sizeof(req->set_dump);
+	req->cookie = NULL;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->set_dump.flag = flag;
+	req->set_dump.nr_lane = nr_lane;
+}
+
 int rnp_mbx_get_capability(struct rte_eth_dev *dev,
 			   int *lane_mask,
 			   int *nic_mode);
@@ -295,4 +361,7 @@  rnp_fw_get_macaddr(struct rte_eth_dev *dev,
 		   u8 *mac_addr,
 		   int nr_lane);
 int rnp_mbx_get_lane_stat(struct rte_eth_dev *dev);
+int rnp_fw_update(struct rnp_eth_adapter *adapter);
+int rnp_hw_set_fw_10g_1g_auto_detch(struct rte_eth_dev *dev, int enable);
+int rnp_hw_set_fw_force_speed_1g(struct rte_eth_dev *dev, int enable);
 #endif /* __RNP_MBX_FW_H__*/