add support ops to set link speed in usermode, and get autoneg stats. Signed-off-by: Junlong Wang --- drivers/net/zxdh/zxdh_ethdev.c | 6 ++ drivers/net/zxdh/zxdh_ethdev.h | 7 +- drivers/net/zxdh/zxdh_ethdev_ops.c | 116 ++++++++++++++++++++++++++--- drivers/net/zxdh/zxdh_ethdev_ops.h | 15 ++++ drivers/net/zxdh/zxdh_msg.c | 49 ++++++++++++ drivers/net/zxdh/zxdh_msg.h | 24 +++++- 6 files changed, 202 insertions(+), 15 deletions(-) diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c index 2fc2d78aff..823b1ffb5c 100644 --- a/drivers/net/zxdh/zxdh_ethdev.c +++ b/drivers/net/zxdh/zxdh_ethdev.c @@ -1432,6 +1432,10 @@ zxdh_dev_start(struct rte_eth_dev *dev) zxdh_queue_notify(vq); } + if (hw->is_pf) + zxdh_link_speed_set(dev); + zxdh_autoneg_stats_get(dev); + hw->admin_status = RTE_ETH_LINK_UP; zxdh_dev_link_update(dev, 0); @@ -1604,6 +1608,8 @@ zxdh_agent_comm(struct rte_eth_dev *eth_dev, struct zxdh_hw *hw) return -1; } + zxdh_speed_modes_get(eth_dev); + if (hw->switchoffload) hw->phyport = 9; diff --git a/drivers/net/zxdh/zxdh_ethdev.h b/drivers/net/zxdh/zxdh_ethdev.h index 411d287f32..81b385ecb8 100644 --- a/drivers/net/zxdh/zxdh_ethdev.h +++ b/drivers/net/zxdh/zxdh_ethdev.h @@ -125,7 +125,7 @@ struct zxdh_hw { uint64_t host_features; uint64_t guest_features; uint32_t speed; - uint32_t speed_mode; + int32_t speed_mode; uint32_t notify_off_multiplier; union zxdh_virport_num vport; uint16_t max_queue_pairs; @@ -173,9 +173,10 @@ struct zxdh_hw { struct zxdh_vlan_offload_cfg vlan_offload_cfg; uint16_t queue_pool_count; uint16_t queue_pool_start; - uint8_t dl_net_hdr_len; uint16_t vxlan_fd_num; - uint8_t rsv1[1]; + uint32_t support_speed_modes; + uint8_t dl_net_hdr_len; + uint8_t autoneg; struct dh_flow_list dh_flow_list; }; diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.c b/drivers/net/zxdh/zxdh_ethdev_ops.c index cabf81107e..8fb315eeac 100644 --- a/drivers/net/zxdh/zxdh_ethdev_ops.c +++ b/drivers/net/zxdh/zxdh_ethdev_ops.c @@ -307,7 +307,7 @@ zxdh_link_info_get(struct rte_eth_dev *dev, struct rte_eth_link *link) } link->link_speed = ZXDH_GET(link_info_msg, link_msg_addr, speed); - link->link_autoneg = ZXDH_GET(link_info_msg, link_msg_addr, autoneg); + // link->link_autoneg = ZXDH_GET(link_info_msg, link_msg_addr, autoneg); hw->speed_mode = ZXDH_GET(link_info_msg, link_msg_addr, speed_modes); if ((ZXDH_GET(link_info_msg, link_msg_addr, duplex) & RTE_ETH_LINK_FULL_DUPLEX) == RTE_ETH_LINK_FULL_DUPLEX) @@ -322,6 +322,7 @@ zxdh_link_info_get(struct rte_eth_dev *dev, struct rte_eth_link *link) link->link_autoneg = RTE_ETH_LINK_AUTONEG; link->link_status = RTE_ETH_LINK_UP; } + link->link_autoneg = hw->autoneg; hw->speed = link->link_speed; return 0; @@ -368,6 +369,109 @@ int zxdh_dev_set_link_up(struct rte_eth_dev *dev) return ret; } +static int32_t zxdh_speed_mode_to_spm(uint32_t link_speed_modes) +{ + switch (link_speed_modes) { + case RTE_ETH_LINK_SPEED_1G: return ZXDH_SPM_SPEED_1X_1G; + case RTE_ETH_LINK_SPEED_10G: return ZXDH_SPM_SPEED_1X_10G; + case RTE_ETH_LINK_SPEED_25G: return ZXDH_SPM_SPEED_1X_25G; + case RTE_ETH_LINK_SPEED_50G: return ZXDH_SPM_SPEED_1X_50G; + case RTE_ETH_LINK_SPEED_100G: return ZXDH_SPM_SPEED_4X_100G; + case RTE_ETH_LINK_SPEED_200G: return ZXDH_SPM_SPEED_4X_200G; + default: return -1; + } +} + +int32_t zxdh_link_speed_set(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + struct zxdh_msg_info msg = {0}; + uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0}; + void *reply_body_addr = ZXDH_ADDR_OF(msg_reply_info, zxdh_msg_reply_info, reply_body); + uint32_t link_speed = 0; + int32_t spm_speed_modes = 0; + int32_t ret = 0; + + spm_speed_modes = + zxdh_speed_mode_to_spm(dev->data->dev_conf.link_speeds & ~RTE_ETH_LINK_SPEED_FIXED); + if (spm_speed_modes == -1 || spm_speed_modes == hw->speed_mode) { + PMD_DRV_LOG(DEBUG, "not need update speed"); + return 0; + } + if ((spm_speed_modes & hw->support_speed_modes) == 0) { + PMD_DRV_LOG(ERR, "not support configure speed :%d ", link_speed); + return 0; + } + + zxdh_agent_msg_build(hw, ZXDH_MAC_SPEED_SET, &msg); + msg.data.link_msg.autoneg = 0; + msg.data.link_msg.speed_modes = spm_speed_modes & hw->support_speed_modes; + + ret = zxdh_send_msg_to_riscv(dev, &msg, sizeof(struct zxdh_msg_info), + zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(msg_reply_info), + ZXDH_BAR_MODULE_MAC); + uint8_t flag = ZXDH_GET(msg_reply_body, reply_body_addr, flag); + if (flag != ZXDH_REPS_SUCC || ret) { + PMD_DRV_LOG(ERR, "failed to set link speed!"); + return -1; + } + + return 0; +} + +void +zxdh_speed_modes_get(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + struct zxdh_msg_info msg = {0}; + uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0}; + int32_t ret = 0; + + if (!hw->is_pf) + return; + + msg.agent_msg_head.msg_type = ZXDH_MAC_PHYPORT_INIT; + msg.agent_msg_head.init = 1; + + ret = zxdh_send_msg_to_riscv(dev, &msg, sizeof(struct zxdh_msg_info), + zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(msg_reply_info), + ZXDH_BAR_MODULE_MAC); + if (ret) + PMD_DRV_LOG(ERR, "Failed to get speed mode info"); + + void *reply_body_addr = ZXDH_ADDR_OF(msg_reply_info, zxdh_msg_reply_info, reply_body); + void *link_msg_addr = ZXDH_ADDR_OF(msg_reply_body, reply_body_addr, link_msg); + uint32_t speed_modes = ZXDH_GET(link_info_msg, link_msg_addr, speed_modes); + + hw->support_speed_modes = speed_modes; +} + +int32_t zxdh_autoneg_stats_get(struct rte_eth_dev *dev) +{ + struct zxdh_hw *hw = dev->data->dev_private; + struct zxdh_msg_info msg; + uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0}; + int32_t ret = 0; + + zxdh_agent_msg_build(hw, ZXDH_MAC_AUTONEG_GET, &msg); + + ret = zxdh_send_msg_to_riscv(dev, &msg, sizeof(struct zxdh_msg_info), + zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(msg_reply_info), + ZXDH_BAR_MODULE_MAC); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to get link autoneg stats!"); + return -1; + } + void *reply_body_addr = ZXDH_ADDR_OF(msg_reply_info, zxdh_msg_reply_info, reply_body); + void *link_addr = ZXDH_ADDR_OF(msg_reply_body, reply_body_addr, link_msg); + void *link_autoeng_addr = ZXDH_ADDR_OF(link_info_msg, link_addr, autoneg); + + hw->autoneg = *(uint8_t *)link_autoeng_addr; + PMD_DRV_LOG(DEBUG, "autoneg stats is: %d", hw->autoneg); + + return 0; +} + int32_t zxdh_dev_link_update(struct rte_eth_dev *dev, int32_t wait_to_complete __rte_unused) { struct rte_eth_link link; @@ -384,17 +488,7 @@ int32_t zxdh_dev_link_update(struct rte_eth_dev *dev, int32_t wait_to_complete _ PMD_DRV_LOG(ERR, "Failed to get link status from hw"); return ret; } - link.link_status &= hw->admin_status; - if (link.link_status == RTE_ETH_LINK_DOWN) { - PMD_DRV_LOG(DEBUG, "dev link status is down."); - goto link_down; - } - goto out; -link_down: - link.link_status = RTE_ETH_LINK_DOWN; - link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN; -out: if (link.link_status != dev->data->dev_link.link_status) { ret = zxdh_config_port_status(dev, link.link_status); if (ret != 0) { diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.h b/drivers/net/zxdh/zxdh_ethdev_ops.h index 85e926887b..6dfe4be473 100644 --- a/drivers/net/zxdh/zxdh_ethdev_ops.h +++ b/drivers/net/zxdh/zxdh_ethdev_ops.h @@ -27,6 +27,18 @@ #define ZXDH_RSS_HF ((ZXDH_HF_MAC_VLAN_ETH | ZXDH_HF_F3_ETH | ZXDH_HF_F5_ETH)) #define ZXDH_ETHER_MIN_MTU 68 +#define ZXDH_SPM_SPEED_1X_10M RTE_BIT32(0) +#define ZXDH_SPM_SPEED_1X_100M RTE_BIT32(1) +#define ZXDH_SPM_SPEED_1X_1G RTE_BIT32(2) +#define ZXDH_SPM_SPEED_1X_2DOT5G RTE_BIT32(3) +#define ZXDH_SPM_SPEED_1X_5G RTE_BIT32(4) +#define ZXDH_SPM_SPEED_1X_10G RTE_BIT32(5) +#define ZXDH_SPM_SPEED_1X_25G RTE_BIT32(6) +#define ZXDH_SPM_SPEED_1X_50G RTE_BIT32(7) +#define ZXDH_SPM_SPEED_2X_100G RTE_BIT32(8) +#define ZXDH_SPM_SPEED_4X_40G RTE_BIT32(9) +#define ZXDH_SPM_SPEED_4X_100G RTE_BIT32(10) +#define ZXDH_SPM_SPEED_4X_200G RTE_BIT32(11) struct zxdh_np_stats_data { uint64_t n_pkts_dropped; @@ -144,5 +156,8 @@ int zxdh_dev_get_module_info(struct rte_eth_dev *dev, struct rte_eth_dev_module_ int zxdh_dev_get_module_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *info); int zxdh_meter_ops_get(struct rte_eth_dev *dev, void *arg); uint16_t zxdh_hw_qid_to_logic_qid(struct rte_eth_dev *dev, uint16_t qid); +int32_t zxdh_link_speed_set(struct rte_eth_dev *dev); +void zxdh_speed_modes_get(struct rte_eth_dev *dev); +int32_t zxdh_autoneg_stats_get(struct rte_eth_dev *dev); #endif /* ZXDH_ETHDEV_OPS_H */ diff --git a/drivers/net/zxdh/zxdh_msg.c b/drivers/net/zxdh/zxdh_msg.c index 196e27f91c..ff2d11706c 100644 --- a/drivers/net/zxdh/zxdh_msg.c +++ b/drivers/net/zxdh/zxdh_msg.c @@ -2450,9 +2450,58 @@ pf_recv_bar_msg(void *pay_load, uint16_t len, void *reps_buffer, return ret; } +static int vf_recv_link_state_msg(struct rte_eth_dev *dev, void *payload, + void *reply_body __rte_unused, uint16_t *reps_len) +{ + struct zxdh_hw *hw = dev->data->dev_private; + void *link_autoneg_addr = ZXDH_ADDR_OF(zxdh_link_state_msg, payload, autoneg_enable); + + hw->autoneg = *(uint8_t *)link_autoneg_addr; + dev->data->dev_link.link_autoneg = hw->autoneg; + *reps_len = ZXDH_ST_SZ_BYTES(zxdh_link_state_msg); + + return 0; +} + +static int +vf_recv_bar_msg(void *payload, uint16_t len __rte_unused, void *reps_buffer, + uint16_t *reps_len, void *eth_dev __rte_unused) +{ + struct zxdh_msg_info *msg_payload = (struct zxdh_msg_info *)payload; + uint16_t pcieid = msg_payload->msg_to_vf.pcieid; + uint16_t opcode = msg_payload->msg_to_vf.opcode; + struct rte_eth_dev *dev = (struct rte_eth_dev *)eth_dev; + struct zxdh_ifc_msg_reply_body_bits *reply_body; + reply_body = (struct zxdh_ifc_msg_reply_body_bits *) + ZXDH_ADDR_OF(msg_reply_body, reps_buffer, flag); + int32_t ret = 0; + + if (dev == NULL) { + PMD_DRV_LOG(ERR, "param invalid, dev is NULL"); + ret = -2; + return ret; + } + + switch (opcode) { + case ZXDH_SET_VF_LINK_STATE: + PMD_DRV_LOG(DEBUG, "PF(pcieid:%d ) set VF's link state", pcieid); + vf_recv_link_state_msg(dev, &msg_payload->data, reps_buffer, reps_len); + reply_body->flag[0] = ZXDH_REPS_SUCC; + break; + default: + ZXDH_SET(msg_reply_body, reps_buffer, flag, ZXDH_REPS_INVALID); + PMD_DRV_LOG(ERR, "[VF GET MSG FROM PF]--unknown msg opcode:%d", opcode); + ret = -1; + break; + } + return ret; +} + void zxdh_msg_cb_reg(struct zxdh_hw *hw) { if (hw->is_pf) zxdh_bar_chan_msg_recv_register(ZXDH_MODULE_BAR_MSG_TO_PF, pf_recv_bar_msg); + else + zxdh_bar_chan_msg_recv_register(ZXDH_MODULE_BAR_MSG_TO_VF, vf_recv_bar_msg); } diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h index 61a3da878e..0fc9bff75d 100644 --- a/drivers/net/zxdh/zxdh_msg.h +++ b/drivers/net/zxdh/zxdh_msg.h @@ -205,6 +205,8 @@ enum zxdh_module_id { enum zxdh_agent_msg_type { ZXDH_MAC_STATS_GET = 10, ZXDH_MAC_STATS_RESET, + ZXDH_MAC_PHYPORT_INIT, + ZXDH_MAC_SPEED_SET, ZXDH_MAC_LINK_GET = 14, ZXDH_MAC_MODULE_EEPROM_READ = 20, ZXDH_VQM_DEV_STATS_GET = 21, @@ -212,6 +214,7 @@ enum zxdh_agent_msg_type { ZXDH_FLASH_FIR_VERSION_GET = 23, ZXDH_VQM_QUEUE_STATS_GET = 24, ZXDH_VQM_QUEUE_STATS_RESET, + ZXDH_MAC_AUTONEG_GET = 44, }; enum zxdh_msg_type { @@ -233,6 +236,7 @@ enum zxdh_msg_type { ZXDH_PORT_ATTRS_SET = 25, ZXDH_PORT_PROMISC_SET = 26, + ZXDH_SET_VF_LINK_STATE = 28, ZXDH_GET_NP_STATS = 31, ZXDH_PLCR_CAR_PROFILE_ID_ADD = 36, @@ -408,6 +412,17 @@ struct zxdh_ifc_agent_mac_module_eeprom_msg_bits { uint8_t data[ZXDH_MODULE_EEPROM_DATA_LEN * 8]; }; +struct zxdh_ifc_zxdh_link_state_msg_bits { + uint8_t is_link_force_set[0x8]; + uint8_t link_forced[0x8]; + uint8_t link_up[0x8]; + uint8_t speed[0x20]; + uint8_t autoneg_enable[0x20]; + uint8_t supported_speed_modes[0x20]; + uint8_t advertising_speed_modes[0x20]; + uint8_t duplex[0x8]; +}; + struct zxdh_flash_msg { uint8_t firmware_version[ZXDH_FWVERS_LEN]; }; @@ -454,6 +469,7 @@ struct zxdh_ifc_msg_reply_body_bits { struct zxdh_ifc_mtr_profile_info_bits mtr_profile_info; struct zxdh_ifc_mtr_stats_bits hw_mtr_stats; struct zxdh_flow_op_rsp flow_rsp; + struct zxdh_ifc_zxdh_link_state_msg_bits link_state_msg; }; }; @@ -482,6 +498,11 @@ struct __rte_packed_begin zxdh_msg_head { uint16_t pcieid; } __rte_packed_end; +struct __rte_packed_begin zxdh_msg_head_to_vf { + uint8_t opcode; + uint16_t pcieid; +} __rte_packed_end; + struct zxdh_port_attr_set_msg { uint32_t mode; uint32_t value; @@ -521,7 +542,7 @@ struct zxdh_agent_msg_head { uint8_t msg_type; uint8_t panel_id; uint8_t phyport; - uint8_t rsv; + uint8_t init; uint16_t vf_id; uint16_t pcie_id; }; @@ -570,6 +591,7 @@ struct zxdh_msg_info { uint8_t head_len[ZXDH_MSG_HEAD_LEN]; struct zxdh_msg_head msg_head; struct zxdh_agent_msg_head agent_msg_head; + struct zxdh_msg_head_to_vf msg_to_vf; }; union { uint8_t datainfo[ZXDH_MSG_REQ_BODY_MAX_LEN]; -- 2.27.0