add various runtime devargs command line options
supported by this driver.

Signed-off-by: Wenbo Cao <caowe...@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(+)

diff --git a/drivers/net/rnp/rnp.h b/drivers/net/rnp/rnp.h
index 6f216cc5ca..933cdc6007 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 ad99f99d4a..5313dae5a2 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 alloced 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 aea4f1d619..d98dd2dcd2 100644
--- a/drivers/net/rnp/rnp_mbx_fw.c
+++ b/drivers/net/rnp/rnp_mbx_fw.c
@@ -106,6 +106,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)
 {
@@ -382,3 +403,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 7bf5c2a865..051ffd1bdc 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__*/
-- 
2.27.0

Reply via email to