This series includes some updates for HNS3 ethernet driver and contains the following contents: 1.refactor and add debugfs cmd; 2.optimize IO path; 3.add support for ptp, imp-controlled PHYs, query tx spare buffer size, RXD advanced layout, handling all errors through MSI-X; 4.clear cleanups for drivers; 5.add capability bits to resolve compatibility; 6.fix drivers bugs;
Baokun Li (2): net: hns3: use list_move_tail instead of list_del/list_add_tail in hclgevf_main.c net: hns3: use list_move_tail instead of list_del/list_add_tail in hclge_main.c
Christophe JAILLET (1): net: hns3: Fix a memory leak in an error handling path in 'hclge_handle_error_info_log()'
Colin Ian King (3): net: hns3: remove redundant null check of an array net: hns3: Fix potential null pointer defererence of null ae_dev net: hns3: Fix return of uninitialized variable ret
Dan Carpenter (2): net: hns3: fix a double shift bug net: hns3: fix different snprintf() limit
Guangbin Huang (18): net: hns3: add interfaces to query information of tm priority/qset net: hns3: add debugfs support for tm nodes, priority and qset info net: hns3: RSS indirection table use device specification net: hns3: debugfs add max tm rate specification print net: hns3: replace macro of max qset number with specification net: hns3: add support for imp-controlled PHYs net: hns3: add get/set pause parameters support for imp-controlled PHYs net: hns3: add ioctl support for imp-controlled PHYs net: hns3: add phy loopback support for imp-controlled PHYs net: hns3: PF add support for pushing link status to VFs net: hns3: VF not request link status when PF support push link status feature net: hns3: refactor dump tm map of debugfs net: hns3: refactor dump tm of debugfs net: hns3: refactor dump tc of debugfs net: hns3: refactor dump qos pause cfg of debugfs net: hns3: refactor dump qos pri map of debugfs net: hns3: refactor dump qos buf cfg of debugfs net: hns3: refactor dump qs shaper of debugfs
GuoJia Liao (1): net: hns3: optimize the code when update the tc info
Guojia Liao (2): net: hns3: split out hclge_tm_vport_tc_info_update() net: hns3: expand the tc config command
Gustavo A. R. Silva (1): net: hns3: fix return of random stack value
Hao Chen (4): net: hns3: refactor out hclge_rm_vport_all_mac_table() net: hns3: refactor queue map of debugfs net: hns3: refactor queue info of debugfs net: hns3: refactor dump fd tcam of debugfs
Huazhong Tan (19): net: hns3: remove redundant return value of hns3_uninit_all_ring() net: hns3: remove an unused parameter in hclge_vf_rate_param_check() net: hns3: refactor out hclge_set_rss_tuple() net: hns3: refactor out hclgevf_set_rss_tuple() net: hns3: remove unused parameter from hclge_dbg_dump_loopback() net: hns3: fix prototype warning net: hns3: fix some typos in hclge_main.c net: hns3: remove a duplicate pf reset counting net: hns3: cleanup inappropriate spaces in struct hlcgevf_tqp_stats net: hns3: change the value of the SEPARATOR_VALUE macro in hclgevf_main.c net: hns3: support RXD advanced layout net: hns3: refactor out RX completion checksum net: hns3: refactor dump bd info of debugfs net: hns3: refactor dump mac list of debugfs net: hns3: fix user's coalesce configuration lost issue net: hns3: switch to dim algorithm for adaptive interrupt moderation net: hns3: add support for PTP net: hns3: add debugfs support for ptp info net: hns3: add support to query tx spare buffer size for pf
Jian Shen (29): net: hns3: add api capability bits for firmware net: hns3: remove redundant client_setup_tc handle net: hns3: cleanup for endian issue for VF RSS net: hns3: refactor out hclge_get_rss_tuple() net: hns3: refactor out hclgevf_get_rss_tuple() net: hns3: split out hclge_dbg_dump_qos_buf_cfg() net: hns3: refactor out hclge_add_fd_entry() net: hns3: refactor out hclge_fd_get_tuple() net: hns3: refactor for function hclge_fd_convert_tuple net: hns3: add support for traffic class tuple support for flow director by ethtool net: hns3: refactor flow director configuration net: hns3: refine for hns3_del_all_fd_entries() net: hns3: add support for user-def data of flow director net: hns3: remove unused code of vmdq net: hns3: fix missing rule state assignment net: hns3: fix use-after-free issue for hclge_add_fd_entry_common() net: hns3: remove the rss_size limitation by vector num net: hns3: configure promisc mode for VF asynchronously net: hns3: use HCLGE_VPORT_STATE_PROMISC_CHANGE to replace HCLGE_STATE_PROMISC_CHANGED net: hns3: add 'QoS' support for port based VLAN configuration net: hns3: refine for hclge_push_vf_port_base_vlan_info() net: hns3: remove unnecessary updating port based VLAN net: hns3: refine function hclge_set_vf_vlan_cfg() net: hns3: add support for modify VLAN filter state net: hns3: add query basic info support for VF net: hns3: add support for VF modify VLAN filter state net: hns3: add debugfs support for vlan configuration net: hns3: add support for FD counter in debugfs net: hns3: add support for dumping MAC umv counter in debugfs
Jiaran Zhang (17): net: hns3: modify some unmacthed types print parameter net: hns3: use ipv6_addr_any() helper net: hns3: remove redundant query in hclge_config_tm_hw_err_int() net: hns3: change flr_prepare/flr_done function names net: hns3: add suspend and resume pm_ops net: hns3: refactor dev capability and dev spec of debugfs net: hns3: refactor dump intr of debugfs net: hns3: refactor dump reset info of debugfs net: hns3: refactor dump m7 info of debugfs net: hns3: refactor dump ncl config of debugfs net: hns3: refactor dump mac tnl status of debugfs net: hns3: add a separate error handling task net: hns3: add scheduling logic for error handling task net: hns3: add the RAS compatibility adaptation solution net: hns3: add support for imp-handle ras capability net: hns3: update error recovery module and type net: hns3: add error handling compatibility during initialization
Liu Jian (1): net: hns3: no return statement in hclge_clear_arfs_rules
Peng Li (10): net: hns3: remove the shaper param magic number net: hns3: change hclge_parse_speed() param type net: hns3: change hclge_query_bd_num() param type net: hns3: remove unused macro definition net: hns3: refactor out hclge_cmd_convert_err_code() net: hns3: refactor out hclgevf_cmd_convert_err_code() net: hns3: clean up hns3_dbg_cmd_write() net: hns3: refactor out hclge_set_vf_vlan_common() net: hns3: remove redundant blank lines net: hns3: remove unused parameter from hclge_set_vf_vlan_common()
Salil Mehta (3): net: hns3: Remove the left over redundant check & assignment net: hns3: Remove un-necessary 'else-if' in the hclge_reset_event() net: hns3: Trivial spell fix in hns3 driver
Yonglong Liu (1): net: hns3: clean up some incorrect variable types in hclge_dbg_dump_tm_map()
Yufeng Mo (18): net: hns3: add support for obtaining the maximum frame size net: hns3: clean up unnecessary parentheses in macro definitions net: hns3: split out hclge_cmd_send() net: hns3: split out hclgevf_cmd_send() net: hns3: use FEC capability queried from firmware net: hns3: use pause capability queried from firmware net: hns3: split function hclge_reset_rebuild() net: hns3: optimize the process of queue reset net: hns3: clear unnecessary reset request in hclge_reset_rebuild net: hns3: refactor the debugfs process net: hns3: refactor dump mng tbl of debugfs net: hns3: refactor dump loopback of debugfs net: hns3: refactor dump reg of debugfs net: hns3: refactor dump reg dcb info of debugfs net: hns3: refactor dump serv info of debugfs net: hns3: remove the useless debugfs file node cmd net: hns3: remove now redundant logic related to HNAE3_UNKNOWN_RESET net: hns3: add support for handling all errors through MSI-X
Yunsheng Lin (9): net: hns3: add tx send size handling for tso skb net: hns3: add stats logging when skb padding fails net: hns3: minor refactor related to desc_cb handling net: hns3: refactor for hns3_fill_desc() function net: hns3: use tx bounce buffer for small packets net: hns3: support dma_map_sg() for multi frags skb net: hns3: optimize the rx page reuse handling process net: hns3: use bounce buffer when rx page can not be reused net: hns3: fix reuse conflict of the rx page
drivers/net/ethernet/hisilicon/Kconfig | 2 + .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 13 +- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 117 +- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 1429 ++++++-- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 64 + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 1448 ++++++-- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 122 +- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 177 +- .../ethernet/hisilicon/hns3/hns3pf/Makefile | 2 +- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 192 +- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 125 +- .../hisilicon/hns3/hns3pf/hclge_dcb.c | 27 - .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 2791 ++++++++++----- .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 47 +- .../hisilicon/hns3/hns3pf/hclge_err.c | 428 ++- .../hisilicon/hns3/hns3pf/hclge_err.h | 89 + .../hisilicon/hns3/hns3pf/hclge_main.c | 3110 +++++++++++------ .../hisilicon/hns3/hns3pf/hclge_main.h | 137 +- .../hisilicon/hns3/hns3pf/hclge_mbx.c | 155 +- .../hisilicon/hns3/hns3pf/hclge_mdio.c | 39 + .../hisilicon/hns3/hns3pf/hclge_mdio.h | 2 + .../hisilicon/hns3/hns3pf/hclge_ptp.c | 542 +++ .../hisilicon/hns3/hns3pf/hclge_ptp.h | 134 + .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 448 ++- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 67 +- .../hisilicon/hns3/hns3vf/hclgevf_cmd.c | 207 +- .../hisilicon/hns3/hns3vf/hclgevf_cmd.h | 28 +- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 361 +- .../hisilicon/hns3/hns3vf/hclgevf_main.h | 16 +- .../hisilicon/hns3/hns3vf/hclgevf_mbx.c | 6 + 30 files changed, 8958 insertions(+), 3367 deletions(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 2bbad0aa40e172e7ed7aba6f6ad4d9977dbd0be3 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Add some interfaces to get information of tm priority and qset, then they can be used by debugfs.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 1 + .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 186 ++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 48 ++++- 3 files changed, 234 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index a731f207b4f1..c6b6894700a9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -160,6 +160,7 @@ enum hclge_opcode_type { HCLGE_OPC_TM_PRI_SCH_MODE_CFG = 0x0813, HCLGE_OPC_TM_QS_SCH_MODE_CFG = 0x0814, HCLGE_OPC_TM_BP_TO_QSET_MAPPING = 0x0815, + HCLGE_OPC_TM_NODES = 0x0816, HCLGE_OPC_ETS_TC_WEIGHT = 0x0843, HCLGE_OPC_QSET_DFX_STS = 0x0844, HCLGE_OPC_PRI_DFX_STS = 0x0845, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 82742a64f3b7..216ab1e92723 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1616,3 +1616,189 @@ int hclge_tm_vport_map_update(struct hclge_dev *hdev)
return hclge_tm_bp_setup(hdev); } + +int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num) +{ + struct hclge_tm_nodes_cmd *nodes; + struct hclge_desc desc; + int ret; + + if (hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) { + /* Each PF has 8 qsets and each VF has 1 qset */ + *qset_num = HCLGE_TM_PF_MAX_QSET_NUM + pci_num_vf(hdev->pdev); + return 0; + } + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NODES, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get qset num, ret = %d\n", ret); + return ret; + } + + nodes = (struct hclge_tm_nodes_cmd *)desc.data; + *qset_num = le16_to_cpu(nodes->qset_num); + return 0; +} + +int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num) +{ + struct hclge_tm_nodes_cmd *nodes; + struct hclge_desc desc; + int ret; + + if (hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) { + *pri_num = HCLGE_TM_PF_MAX_PRI_NUM; + return 0; + } + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NODES, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get pri num, ret = %d\n", ret); + return ret; + } + + nodes = (struct hclge_tm_nodes_cmd *)desc.data; + *pri_num = nodes->pri_num; + return 0; +} + +int hclge_tm_get_qset_map_pri(struct hclge_dev *hdev, u16 qset_id, u8 *priority, + u8 *link_vld) +{ + struct hclge_qs_to_pri_link_cmd *map; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_TO_PRI_LINK, true); + map = (struct hclge_qs_to_pri_link_cmd *)desc.data; + map->qs_id = cpu_to_le16(qset_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get qset map priority, ret = %d\n", ret); + return ret; + } + + *priority = map->priority; + *link_vld = map->link_vld; + return 0; +} + +int hclge_tm_get_qset_sch_mode(struct hclge_dev *hdev, u16 qset_id, u8 *mode) +{ + struct hclge_qs_sch_mode_cfg_cmd *qs_sch_mode; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, true); + qs_sch_mode = (struct hclge_qs_sch_mode_cfg_cmd *)desc.data; + qs_sch_mode->qs_id = cpu_to_le16(qset_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get qset sch mode, ret = %d\n", ret); + return ret; + } + + *mode = qs_sch_mode->sch_mode; + return 0; +} + +int hclge_tm_get_qset_weight(struct hclge_dev *hdev, u16 qset_id, u8 *weight) +{ + struct hclge_qs_weight_cmd *qs_weight; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_WEIGHT, true); + qs_weight = (struct hclge_qs_weight_cmd *)desc.data; + qs_weight->qs_id = cpu_to_le16(qset_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get qset weight, ret = %d\n", ret); + return ret; + } + + *weight = qs_weight->dwrr; + return 0; +} + +int hclge_tm_get_pri_sch_mode(struct hclge_dev *hdev, u8 pri_id, u8 *mode) +{ + struct hclge_pri_sch_mode_cfg_cmd *pri_sch_mode; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, true); + pri_sch_mode = (struct hclge_pri_sch_mode_cfg_cmd *)desc.data; + pri_sch_mode->pri_id = pri_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get priority sch mode, ret = %d\n", ret); + return ret; + } + + *mode = pri_sch_mode->sch_mode; + return 0; +} + +int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight) +{ + struct hclge_priority_weight_cmd *priority_weight; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_WEIGHT, true); + priority_weight = (struct hclge_priority_weight_cmd *)desc.data; + priority_weight->pri_id = pri_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get priority weight, ret = %d\n", ret); + return ret; + } + + *weight = priority_weight->dwrr; + return 0; +} + +int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id, + enum hclge_opcode_type cmd, + struct hclge_pri_shaper_para *para) +{ + struct hclge_pri_shapping_cmd *shap_cfg_cmd; + struct hclge_desc desc; + u32 shapping_para; + int ret; + + if (cmd != HCLGE_OPC_TM_PRI_C_SHAPPING && + cmd != HCLGE_OPC_TM_PRI_P_SHAPPING) + return -EINVAL; + + hclge_cmd_setup_basic_desc(&desc, cmd, true); + shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data; + shap_cfg_cmd->pri_id = pri_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get priority shaper(%#x), ret = %d\n", + cmd, ret); + return ret; + } + + shapping_para = le32_to_cpu(shap_cfg_cmd->pri_shapping_para); + para->ir_b = hclge_tm_get_field(shapping_para, IR_B); + para->ir_u = hclge_tm_get_field(shapping_para, IR_U); + para->ir_s = hclge_tm_get_field(shapping_para, IR_S); + para->bs_b = hclge_tm_get_field(shapping_para, BS_B); + para->bs_s = hclge_tm_get_field(shapping_para, BS_S); + para->flag = shap_cfg_cmd->flag; + para->rate = le32_to_cpu(shap_cfg_cmd->pri_rate); + return 0; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index 5498d73ed34b..d33cb04acbef 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -21,6 +21,9 @@
#define HCLGE_ETHER_MAX_RATE 100000
+#define HCLGE_TM_PF_MAX_PRI_NUM 8 +#define HCLGE_TM_PF_MAX_QSET_NUM 8 + struct hclge_pg_to_pri_link_cmd { u8 pg_id; u8 rsvd1[3]; @@ -65,6 +68,18 @@ struct hclge_priority_weight_cmd { u8 dwrr; };
+struct hclge_pri_sch_mode_cfg_cmd { + u8 pri_id; + u8 rsvd[3]; + u8 sch_mode; +}; + +struct hclge_qs_sch_mode_cfg_cmd { + __le16 qs_id; + u8 rsvd[2]; + u8 sch_mode; +}; + struct hclge_qs_weight_cmd { __le16 qs_id; u8 dwrr; @@ -173,6 +188,27 @@ struct hclge_shaper_ir_para { u8 ir_s; /* IR_S parameter of IR shaper */ };
+struct hclge_tm_nodes_cmd { + u8 pg_base_id; + u8 pri_base_id; + __le16 qset_base_id; + __le16 queue_base_id; + u8 pg_num; + u8 pri_num; + __le16 qset_num; + __le16 queue_num; +}; + +struct hclge_pri_shaper_para { + u8 ir_b; + u8 ir_u; + u8 ir_s; + u8 bs_b; + u8 bs_s; + u8 flag; + u32 rate; +}; + #define hclge_tm_set_field(dest, string, val) \ hnae3_set_field((dest), \ (HCLGE_TM_SHAP_##string##_MSK), \ @@ -195,5 +231,15 @@ int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate); - +int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num); +int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num); +int hclge_tm_get_qset_map_pri(struct hclge_dev *hdev, u16 qset_id, u8 *priority, + u8 *link_vld); +int hclge_tm_get_qset_sch_mode(struct hclge_dev *hdev, u16 qset_id, u8 *mode); +int hclge_tm_get_qset_weight(struct hclge_dev *hdev, u16 qset_id, u8 *weight); +int hclge_tm_get_pri_sch_mode(struct hclge_dev *hdev, u8 pri_id, u8 *mode); +int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight); +int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id, + enum hclge_opcode_type cmd, + struct hclge_pri_shaper_para *para); #endif
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 04987ca1b9b6841cfa5f9b459c5a270b75c89345 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
In order to query tm info of nodes, priority and qset for debugging, adds three debugfs files tm_nodes, tm_priority and tm_qset in newly created tm directory.
Unlike previous debugfs commands, these three files just support read ops, so they only support to use cat command to dump their info.
The new tm file style is acccording to suggestion from Jakub Kicinski's opinion as link https://lkml.org/lkml/2020/9/29/2101.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 8 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 55 ++++++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 153 ++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 1 + .../hisilicon/hns3/hns3pf/hclge_main.h | 2 + 5 files changed, 218 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 99fc79d919b9..898879a2c8fe 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -464,6 +464,8 @@ struct hnae3_ae_dev { * Delete clsflower rule * cls_flower_active * Check if any cls flower rule exist + * dbg_read_cmd + * Execute debugfs read command. */ struct hnae3_ae_ops { int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev); @@ -619,6 +621,8 @@ struct hnae3_ae_ops { int (*add_arfs_entry)(struct hnae3_handle *handle, u16 queue_id, u16 flow_id, struct flow_keys *fkeys); int (*dbg_run_cmd)(struct hnae3_handle *handle, const char *cmd_buf); + int (*dbg_read_cmd)(struct hnae3_handle *handle, const char *cmd_buf, + char *buf, int len); pci_ers_result_t (*handle_hw_ras_error)(struct hnae3_ae_dev *ae_dev); bool (*get_hw_reset_stat)(struct hnae3_handle *handle); bool (*ae_dev_resetting)(struct hnae3_handle *handle); @@ -776,6 +780,10 @@ struct hnae3_handle { #define hnae3_get_bit(origin, shift) \ hnae3_get_field((origin), (0x1 << (shift)), (shift))
+#define HNAE3_DBG_TM_NODES "tm_nodes" +#define HNAE3_DBG_TM_PRI "tm_priority" +#define HNAE3_DBG_TM_QSET "tm_qset" + int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev); void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 9d4e9c053a8f..6978304f1ac5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -7,7 +7,7 @@ #include "hnae3.h" #include "hns3_enet.h"
-#define HNS3_DBG_READ_LEN 256 +#define HNS3_DBG_READ_LEN 65536 #define HNS3_DBG_WRITE_LEN 1024
static struct dentry *hns3_dbgfs_root; @@ -484,6 +484,42 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, return count; }
+static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct hnae3_handle *handle = filp->private_data; + const struct hnae3_ae_ops *ops = handle->ae_algo->ops; + struct hns3_nic_priv *priv = handle->priv; + char *cmd_buf, *read_buf; + ssize_t size = 0; + int ret = 0; + + if (!filp->f_path.dentry->d_iname) + return -EINVAL; + + read_buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); + if (!read_buf) + return -ENOMEM; + + cmd_buf = filp->f_path.dentry->d_iname; + + if (ops->dbg_read_cmd) + ret = ops->dbg_read_cmd(handle, cmd_buf, read_buf, + HNS3_DBG_READ_LEN); + + if (ret) { + dev_info(priv->dev, "unknown command\n"); + goto out; + } + + size = simple_read_from_buffer(buffer, count, ppos, read_buf, + strlen(read_buf)); + +out: + kfree(read_buf); + return size; +} + static const struct file_operations hns3_dbg_cmd_fops = { .owner = THIS_MODULE, .open = simple_open, @@ -491,14 +527,31 @@ static const struct file_operations hns3_dbg_cmd_fops = { .write = hns3_dbg_cmd_write, };
+static const struct file_operations hns3_dbg_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = hns3_dbg_read, +}; + void hns3_dbg_init(struct hnae3_handle *handle) { + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev); const char *name = pci_name(handle->pdev); + struct dentry *entry_dir;
handle->hnae3_dbgfs = debugfs_create_dir(name, hns3_dbgfs_root);
debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, &hns3_dbg_cmd_fops); + + entry_dir = debugfs_create_dir("tm", handle->hnae3_dbgfs); + if (ae_dev->dev_version > HNAE3_DEVICE_VERSION_V2) + debugfs_create_file(HNAE3_DBG_TM_NODES, 0600, entry_dir, handle, + &hns3_dbg_fops); + debugfs_create_file(HNAE3_DBG_TM_PRI, 0600, entry_dir, handle, + &hns3_dbg_fops); + debugfs_create_file(HNAE3_DBG_TM_QSET, 0600, entry_dir, handle, + &hns3_dbg_fops); }
void hns3_dbg_uninit(struct hnae3_handle *handle) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 8f6dea5198cf..8f3fefe50719 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -800,6 +800,140 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, cmd, ret); }
+static int hclge_dbg_dump_tm_nodes(struct hclge_dev *hdev, char *buf, int len) +{ + struct hclge_tm_nodes_cmd *nodes; + struct hclge_desc desc; + int pos = 0; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NODES, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump tm nodes, ret = %d\n", ret); + return ret; + } + + nodes = (struct hclge_tm_nodes_cmd *)desc.data; + + pos += scnprintf(buf + pos, len - pos, " BASE_ID MAX_NUM\n"); + pos += scnprintf(buf + pos, len - pos, "PG %4u %4u\n", + nodes->pg_base_id, nodes->pg_num); + pos += scnprintf(buf + pos, len - pos, "PRI %4u %4u\n", + nodes->pri_base_id, nodes->pri_num); + pos += scnprintf(buf + pos, len - pos, "QSET %4u %4u\n", + le16_to_cpu(nodes->qset_base_id), + le16_to_cpu(nodes->qset_num)); + pos += scnprintf(buf + pos, len - pos, "QUEUE %4u %4u\n", + le16_to_cpu(nodes->queue_base_id), + le16_to_cpu(nodes->queue_num)); + + return 0; +} + +static int hclge_dbg_dump_tm_pri(struct hclge_dev *hdev, char *buf, int len) +{ + struct hclge_pri_shaper_para c_shaper_para; + struct hclge_pri_shaper_para p_shaper_para; + u8 pri_num, sch_mode, weight; + char *sch_mode_str; + int pos = 0; + int ret; + u8 i; + + ret = hclge_tm_get_pri_num(hdev, &pri_num); + if (ret) + return ret; + + pos += scnprintf(buf + pos, len - pos, + "ID MODE DWRR C_IR_B C_IR_U C_IR_S C_BS_B "); + pos += scnprintf(buf + pos, len - pos, + "C_BS_S C_FLAG C_RATE(Mbps) P_IR_B P_IR_U "); + pos += scnprintf(buf + pos, len - pos, + "P_IR_S P_BS_B P_BS_S P_FLAG P_RATE(Mbps)\n"); + + for (i = 0; i < pri_num; i++) { + ret = hclge_tm_get_pri_sch_mode(hdev, i, &sch_mode); + if (ret) + return ret; + + ret = hclge_tm_get_pri_weight(hdev, i, &weight); + if (ret) + return ret; + + ret = hclge_tm_get_pri_shaper(hdev, i, + HCLGE_OPC_TM_PRI_C_SHAPPING, + &c_shaper_para); + if (ret) + return ret; + + ret = hclge_tm_get_pri_shaper(hdev, i, + HCLGE_OPC_TM_PRI_P_SHAPPING, + &p_shaper_para); + if (ret) + return ret; + + sch_mode_str = sch_mode & HCLGE_TM_TX_SCHD_DWRR_MSK ? "dwrr" : + "sp"; + + pos += scnprintf(buf + pos, len - pos, + "%04u %4s %3u %3u %3u %3u ", + i, sch_mode_str, weight, c_shaper_para.ir_b, + c_shaper_para.ir_u, c_shaper_para.ir_s); + pos += scnprintf(buf + pos, len - pos, + "%3u %3u %1u %6u ", + c_shaper_para.bs_b, c_shaper_para.bs_s, + c_shaper_para.flag, c_shaper_para.rate); + pos += scnprintf(buf + pos, len - pos, + "%3u %3u %3u %3u %3u ", + p_shaper_para.ir_b, p_shaper_para.ir_u, + p_shaper_para.ir_s, p_shaper_para.bs_b, + p_shaper_para.bs_s); + pos += scnprintf(buf + pos, len - pos, "%1u %6u\n", + p_shaper_para.flag, p_shaper_para.rate); + } + + return 0; +} + +static int hclge_dbg_dump_tm_qset(struct hclge_dev *hdev, char *buf, int len) +{ + u8 priority, link_vld, sch_mode, weight; + char *sch_mode_str; + int ret, pos; + u16 qset_num; + u16 i; + + ret = hclge_tm_get_qset_num(hdev, &qset_num); + if (ret) + return ret; + + pos = scnprintf(buf, len, "ID MAP_PRI LINK_VLD MODE DWRR\n"); + + for (i = 0; i < qset_num; i++) { + ret = hclge_tm_get_qset_map_pri(hdev, i, &priority, &link_vld); + if (ret) + return ret; + + ret = hclge_tm_get_qset_sch_mode(hdev, i, &sch_mode); + if (ret) + return ret; + + ret = hclge_tm_get_qset_weight(hdev, i, &weight); + if (ret) + return ret; + + sch_mode_str = sch_mode & HCLGE_TM_TX_SCHD_DWRR_MSK ? "dwrr" : + "sp"; + pos += scnprintf(buf + pos, len - pos, + "%04u %4u %1u %4s %3u\n", + i, priority, link_vld, sch_mode_str, weight); + } + + return 0; +} + static void hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev) { struct hclge_cfg_pause_param_cmd *pause_param; @@ -1591,3 +1725,22 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
return 0; } + +int hclge_dbg_read_cmd(struct hnae3_handle *handle, const char *cmd_buf, + char *buf, int len) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + + if (strncmp(cmd_buf, HNAE3_DBG_TM_NODES, + strlen(HNAE3_DBG_TM_NODES)) == 0) + return hclge_dbg_dump_tm_nodes(hdev, buf, len); + else if (strncmp(cmd_buf, HNAE3_DBG_TM_PRI, + strlen(HNAE3_DBG_TM_PRI)) == 0) + return hclge_dbg_dump_tm_pri(hdev, buf, len); + else if (strncmp(cmd_buf, HNAE3_DBG_TM_QSET, + strlen(HNAE3_DBG_TM_QSET)) == 0) + return hclge_dbg_dump_tm_qset(hdev, buf, len); + + return -EINVAL; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 1c13cf34ae9f..73022c3496aa 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11869,6 +11869,7 @@ static const struct hnae3_ae_ops hclge_ops = { .enable_fd = hclge_enable_fd, .add_arfs_entry = hclge_add_fd_entry_by_arfs, .dbg_run_cmd = hclge_dbg_run_cmd, + .dbg_read_cmd = hclge_dbg_read_cmd, .handle_hw_ras_error = hclge_handle_hw_ras_error, .get_hw_reset_stat = hclge_get_hw_reset_stat, .ae_dev_resetting = hclge_ae_dev_resetting, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index ca46bc9110d7..32e5f82ef615 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1006,6 +1006,8 @@ int hclge_vport_start(struct hclge_vport *vport); void hclge_vport_stop(struct hclge_vport *vport); int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu); int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf); +int hclge_dbg_read_cmd(struct hnae3_handle *handle, const char *cmd_buf, + char *buf, int len); u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id); int hclge_notify_client(struct hclge_dev *hdev, enum hnae3_reset_notify_type type);
From: Colin Ian King colin.king@canonical.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 8f8a42ff003aaa3c1424923154c9a92f3bd4c634 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The null check of filp->f_path.dentry->d_iname is redundant because it is an array of DNAME_INLINE_LEN chars and cannot be a null. Fix this by removing the null check.
Addresses-Coverity: ("Array compared against 0") Fixes: 04987ca1b9b6 ("net: hns3: add debugfs support for tm nodes, priority and qset info") Signed-off-by: Colin Ian King colin.king@canonical.com Reviewed-by: Jesse Brandeburg jesse.brandeburg@intel.com Link: https://lore.kernel.org/r/20210203131040.21656-1-colin.king@canonical.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 6978304f1ac5..c5958754f939 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -494,9 +494,6 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, ssize_t size = 0; int ret = 0;
- if (!filp->f_path.dentry->d_iname) - return -EINVAL; - read_buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); if (!read_buf) return -ENOMEM;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 1cef42c8474f22d6a8509a19c0b578e5f60138d9 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To improve the compatibility of firmware for driver, help firmware to deal with different api commands, add api capability bits when initialize the command queue.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 10 ++++++++++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 6 +++++- .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 10 ++++++++++ .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 6 +++++- 4 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index b728be4737f8..6546b47bef88 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -363,6 +363,15 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps); }
+static __le32 hclge_build_api_caps(void) +{ + u32 api_caps = 0; + + hnae3_set_bit(api_caps, HCLGE_API_CAP_FLEX_RSS_TBL_B, 1); + + return cpu_to_le32(api_caps); +} + static enum hclge_cmd_status hclge_cmd_query_version_and_capability(struct hclge_dev *hdev) { @@ -373,6 +382,7 @@ hclge_cmd_query_version_and_capability(struct hclge_dev *hdev)
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_FW_VER, 1); resp = (struct hclge_query_version_cmd *)desc.data; + resp->api_caps = hclge_build_api_caps();
ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index c6b6894700a9..2bbb569aee55 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -386,11 +386,15 @@ enum HCLGE_CAP_BITS { HCLGE_CAP_UDP_TUNNEL_CSUM_B, };
+enum HCLGE_API_CAP_BITS { + HCLGE_API_CAP_FLEX_RSS_TBL_B, +}; + #define HCLGE_QUERY_CAP_LENGTH 3 struct hclge_query_version_cmd { __le32 firmware; __le32 hardware; - __le32 rsv; + __le32 api_caps; __le32 caps[HCLGE_QUERY_CAP_LENGTH]; /* capabilities of device */ };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index e04c0cfeb95c..0f93c2dd890d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -342,6 +342,15 @@ static void hclgevf_parse_capability(struct hclgevf_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps); }
+static __le32 hclgevf_build_api_caps(void) +{ + u32 api_caps = 0; + + hnae3_set_bit(api_caps, HCLGEVF_API_CAP_FLEX_RSS_TBL_B, 1); + + return cpu_to_le32(api_caps); +} + static int hclgevf_cmd_query_version_and_capability(struct hclgevf_dev *hdev) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); @@ -352,6 +361,7 @@ static int hclgevf_cmd_query_version_and_capability(struct hclgevf_dev *hdev) resp = (struct hclgevf_query_version_cmd *)desc.data;
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_QUERY_FW_VER, 1); + resp->api_caps = hclgevf_build_api_caps(); status = hclgevf_cmd_send(&hdev->hw, &desc, 1); if (status) return status; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 82eed258e8c1..d591b33a5698 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -161,11 +161,15 @@ enum HCLGEVF_CAP_BITS { HCLGEVF_CAP_UDP_TUNNEL_CSUM_B, };
+enum HCLGEVF_API_CAP_BITS { + HCLGEVF_API_CAP_FLEX_RSS_TBL_B, +}; + #define HCLGEVF_QUERY_CAP_LENGTH 3 struct hclgevf_query_version_cmd { __le32 firmware; __le32 hardware; - __le32 rsv; + __le32 api_caps; __le32 caps[HCLGEVF_QUERY_CAP_LENGTH]; /* capabilities of device */ };
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 87ce161e8c67aca9e64a77355f748e212122ace4 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
As RSS indirection table size may be different in different hardware. Instead of using macro, this value is better to use device specification which querying from firmware.
BTW, RSS indirection table should be allocated by the queried size instead the static array.
.get_rss_indir_size in struct hnae3_ae_ops is not used now, so remove it as well.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 3 -- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 6 +-- .../hisilicon/hns3/hns3pf/hclge_main.c | 45 +++++++++++++------ .../hisilicon/hns3/hns3pf/hclge_main.h | 4 +- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 43 ++++++++++++------ .../hisilicon/hns3/hns3vf/hclgevf_main.h | 6 +-- 6 files changed, 66 insertions(+), 41 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 898879a2c8fe..0e4e18a10413 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -409,8 +409,6 @@ struct hnae3_ae_dev { * Get the len of the regs dump * get_rss_key_size() * Get rss key size - * get_rss_indir_size() - * Get rss indirection table size * get_rss() * Get rss table * set_rss() @@ -554,7 +552,6 @@ struct hnae3_ae_ops { int (*get_regs_len)(struct hnae3_handle *handle);
u32 (*get_rss_key_size)(struct hnae3_handle *handle); - u32 (*get_rss_indir_size)(struct hnae3_handle *handle); int (*get_rss)(struct hnae3_handle *handle, u32 *indir, u8 *key, u8 *hfunc); int (*set_rss)(struct hnae3_handle *handle, const u32 *indir, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 7276cfaa8c3b..6828432cb3be 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -861,11 +861,9 @@ static u32 hns3_get_rss_key_size(struct net_device *netdev) static u32 hns3_get_rss_indir_size(struct net_device *netdev) { struct hnae3_handle *h = hns3_get_handle(netdev); + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
- if (!h->ae_algo->ops->get_rss_indir_size) - return 0; - - return h->ae_algo->ops->get_rss_indir_size(h); + return ae_dev->dev_specs.rss_ind_tbl_size; }
static int hns3_get_rss(struct net_device *netdev, u32 *indir, u8 *key, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 73022c3496aa..5a549194f205 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4237,11 +4237,6 @@ static u32 hclge_get_rss_key_size(struct hnae3_handle *handle) return HCLGE_RSS_KEY_SIZE; }
-static u32 hclge_get_rss_indir_size(struct hnae3_handle *handle) -{ - return HCLGE_RSS_IND_TBL_SIZE; -} - static int hclge_set_rss_algo_key(struct hclge_dev *hdev, const u8 hfunc, const u8 *key) { @@ -4283,6 +4278,7 @@ static int hclge_set_rss_indir_table(struct hclge_dev *hdev, const u16 *indir) { struct hclge_rss_indirection_table_cmd *req; struct hclge_desc desc; + int rss_cfg_tbl_num; u8 rss_msb_oft; u8 rss_msb_val; int ret; @@ -4291,8 +4287,10 @@ static int hclge_set_rss_indir_table(struct hclge_dev *hdev, const u16 *indir) u32 j;
req = (struct hclge_rss_indirection_table_cmd *)desc.data; + rss_cfg_tbl_num = hdev->ae_dev->dev_specs.rss_ind_tbl_size / + HCLGE_RSS_CFG_TBL_SIZE;
- for (i = 0; i < HCLGE_RSS_CFG_TBL_NUM; i++) { + for (i = 0; i < rss_cfg_tbl_num; i++) { hclge_cmd_setup_basic_desc (&desc, HCLGE_OPC_RSS_INDIR_TABLE, false);
@@ -4398,6 +4396,7 @@ static int hclge_set_rss_input_tuple(struct hclge_dev *hdev) static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, u8 *hfunc) { + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev); struct hclge_vport *vport = hclge_get_vport(handle); int i;
@@ -4422,7 +4421,7 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir,
/* Get indirect table */ if (indir) - for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++) indir[i] = vport->rss_indirection_tbl[i];
return 0; @@ -4431,6 +4430,7 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir, static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, const u8 *key, const u8 hfunc) { + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev); struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; u8 hash_algo; @@ -4462,7 +4462,7 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir, }
/* Update the shadow RSS table with user specified qids */ - for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++) vport->rss_indirection_tbl[i] = indir[i];
/* Update the hardware */ @@ -4703,14 +4703,15 @@ void hclge_rss_indir_init_cfg(struct hclge_dev *hdev) int i, j;
for (j = 0; j < hdev->num_vmdq_vport + 1; j++) { - for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++) vport[j].rss_indirection_tbl[i] = i % vport[j].alloc_rss_size; } }
-static void hclge_rss_init_cfg(struct hclge_dev *hdev) +static int hclge_rss_init_cfg(struct hclge_dev *hdev) { + u16 rss_ind_tbl_size = hdev->ae_dev->dev_specs.rss_ind_tbl_size; int i, rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; struct hclge_vport *vport = hdev->vport;
@@ -4718,6 +4719,8 @@ static void hclge_rss_init_cfg(struct hclge_dev *hdev) rss_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { + u16 *rss_ind_tbl; + vport[i].rss_tuple_sets.ipv4_tcp_en = HCLGE_RSS_INPUT_TUPLE_OTHER; vport[i].rss_tuple_sets.ipv4_udp_en = @@ -4739,11 +4742,19 @@ static void hclge_rss_init_cfg(struct hclge_dev *hdev)
vport[i].rss_algo = rss_algo;
+ rss_ind_tbl = devm_kcalloc(&hdev->pdev->dev, rss_ind_tbl_size, + sizeof(*rss_ind_tbl), GFP_KERNEL); + if (!rss_ind_tbl) + return -ENOMEM; + + vport[i].rss_indirection_tbl = rss_ind_tbl; memcpy(vport[i].rss_hash_key, hclge_hash_key, HCLGE_RSS_KEY_SIZE); }
hclge_rss_indir_init_cfg(hdev); + + return 0; }
int hclge_bind_ring_with_vector(struct hclge_vport *vport, @@ -10587,7 +10598,12 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) goto err_mdiobus_unreg; }
- hclge_rss_init_cfg(hdev); + ret = hclge_rss_init_cfg(hdev); + if (ret) { + dev_err(&pdev->dev, "failed to init rss cfg, ret = %d\n", ret); + goto err_mdiobus_unreg; + } + ret = hclge_rss_init_hw(hdev); if (ret) { dev_err(&pdev->dev, "Rss init fail, ret =%d\n", ret); @@ -11078,6 +11094,7 @@ static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle, static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, bool rxfh_configured) { + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev); struct hclge_vport *vport = hclge_get_vport(handle); struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; u16 tc_offset[HCLGE_MAX_TC_NUM] = {0}; @@ -11121,11 +11138,12 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, goto out;
/* Reinitializes the rss indirect table according to the new RSS size */ - rss_indir = kcalloc(HCLGE_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL); + rss_indir = kcalloc(ae_dev->dev_specs.rss_ind_tbl_size, sizeof(u32), + GFP_KERNEL); if (!rss_indir) return -ENOMEM;
- for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++) rss_indir[i] = i % kinfo->rss_size;
ret = hclge_set_rss(handle, rss_indir, NULL, 0); @@ -11818,7 +11836,6 @@ static const struct hnae3_ae_ops hclge_ops = { .get_fec = hclge_get_fec, .set_fec = hclge_set_fec, .get_rss_key_size = hclge_get_rss_key_size, - .get_rss_indir_size = hclge_get_rss_indir_size, .get_rss = hclge_get_rss, .set_rss = hclge_set_rss, .set_rss_tuple = hclge_set_rss_tuple, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 32e5f82ef615..a9c67e3891eb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -97,8 +97,6 @@ #define HCLGE_RSS_HASH_ALGO_SIMPLE 1 #define HCLGE_RSS_HASH_ALGO_SYMMETRIC 2 #define HCLGE_RSS_HASH_ALGO_MASK GENMASK(3, 0) -#define HCLGE_RSS_CFG_TBL_NUM \ - (HCLGE_RSS_IND_TBL_SIZE / HCLGE_RSS_CFG_TBL_SIZE)
#define HCLGE_RSS_INPUT_TUPLE_OTHER GENMASK(3, 0) #define HCLGE_RSS_INPUT_TUPLE_SCTP GENMASK(4, 0) @@ -922,7 +920,7 @@ struct hclge_vport {
u8 rss_hash_key[HCLGE_RSS_KEY_SIZE]; /* User configured hash keys */ /* User configured lookup table entries */ - u16 rss_indirection_tbl[HCLGE_RSS_IND_TBL_SIZE]; + u16 *rss_indirection_tbl; int rss_algo; /* User configured hash algorithm */ /* User configured rss tuple sets */ struct hclge_rss_tuple_cfg rss_tuple_sets; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 3bd7bc794677..090591e3f087 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -642,22 +642,20 @@ static u32 hclgevf_get_rss_key_size(struct hnae3_handle *handle) return HCLGEVF_RSS_KEY_SIZE; }
-static u32 hclgevf_get_rss_indir_size(struct hnae3_handle *handle) -{ - return HCLGEVF_RSS_IND_TBL_SIZE; -} - static int hclgevf_set_rss_indir_table(struct hclgevf_dev *hdev) { const u8 *indir = hdev->rss_cfg.rss_indirection_tbl; struct hclgevf_rss_indirection_table_cmd *req; struct hclgevf_desc desc; + int rss_cfg_tbl_num; int status; int i, j;
req = (struct hclgevf_rss_indirection_table_cmd *)desc.data; + rss_cfg_tbl_num = hdev->ae_dev->dev_specs.rss_ind_tbl_size / + HCLGEVF_RSS_CFG_TBL_SIZE;
- for (i = 0; i < HCLGEVF_RSS_CFG_TBL_NUM; i++) { + for (i = 0; i < rss_cfg_tbl_num; i++) { hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INDIR_TABLE, false); req->start_table_index = i * HCLGEVF_RSS_CFG_TBL_SIZE; @@ -795,7 +793,7 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, }
if (indir) - for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++) indir[i] = rss_cfg->rss_indirection_tbl[i];
return 0; @@ -838,7 +836,7 @@ static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir, }
/* update the shadow RSS table with user specified qids */ - for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++) rss_cfg->rss_indirection_tbl[i] = indir[i];
/* update the hardware */ @@ -2482,8 +2480,9 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en) return ret; }
-static void hclgevf_rss_init_cfg(struct hclgevf_dev *hdev) +static int hclgevf_rss_init_cfg(struct hclgevf_dev *hdev) { + u16 rss_ind_tbl_size = hdev->ae_dev->dev_specs.rss_ind_tbl_size; struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; struct hclgevf_rss_tuple_cfg *tuple_sets; u32 i; @@ -2492,7 +2491,16 @@ static void hclgevf_rss_init_cfg(struct hclgevf_dev *hdev) rss_cfg->rss_size = hdev->nic.kinfo.rss_size; tuple_sets = &rss_cfg->rss_tuple_sets; if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { + u8 *rss_ind_tbl; + rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE; + + rss_ind_tbl = devm_kcalloc(&hdev->pdev->dev, rss_ind_tbl_size, + sizeof(*rss_ind_tbl), GFP_KERNEL); + if (!rss_ind_tbl) + return -ENOMEM; + + rss_cfg->rss_indirection_tbl = rss_ind_tbl; memcpy(rss_cfg->rss_hash_key, hclgevf_hash_key, HCLGEVF_RSS_KEY_SIZE);
@@ -2510,8 +2518,10 @@ static void hclgevf_rss_init_cfg(struct hclgevf_dev *hdev) }
/* Initialize RSS indirect table */ - for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < rss_ind_tbl_size; i++) rss_cfg->rss_indirection_tbl[i] = i % rss_cfg->rss_size; + + return 0; }
static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) @@ -3266,7 +3276,12 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) goto err_config;
/* Initialize RSS for this VF */ - hclgevf_rss_init_cfg(hdev); + ret = hclgevf_rss_init_cfg(hdev); + if (ret) { + dev_err(&pdev->dev, "failed to init rss cfg, ret = %d\n", ret); + goto err_config; + } + ret = hclgevf_rss_init_hw(hdev); if (ret) { dev_err(&hdev->pdev->dev, @@ -3444,11 +3459,12 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, goto out;
/* Reinitializes the rss indirect table according to the new RSS size */ - rss_indir = kcalloc(HCLGEVF_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL); + rss_indir = kcalloc(hdev->ae_dev->dev_specs.rss_ind_tbl_size, + sizeof(u32), GFP_KERNEL); if (!rss_indir) return -ENOMEM;
- for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++) + for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++) rss_indir[i] = i % kinfo->rss_size;
hdev->rss_cfg.rss_size = kinfo->rss_size; @@ -3687,7 +3703,6 @@ static const struct hnae3_ae_ops hclgevf_ops = { .get_strings = hclgevf_get_strings, .get_sset_count = hclgevf_get_sset_count, .get_rss_key_size = hclgevf_get_rss_key_size, - .get_rss_indir_size = hclgevf_get_rss_indir_size, .get_rss = hclgevf_get_rss, .set_rss = hclgevf_set_rss, .get_rss_tuple = hclgevf_get_rss_tuple, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index f6d817a3edcb..6147bd74d4a2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -113,8 +113,7 @@ #define HCLGEVF_RSS_HASH_ALGO_SIMPLE 1 #define HCLGEVF_RSS_HASH_ALGO_SYMMETRIC 2 #define HCLGEVF_RSS_HASH_ALGO_MASK 0xf -#define HCLGEVF_RSS_CFG_TBL_NUM \ - (HCLGEVF_RSS_IND_TBL_SIZE / HCLGEVF_RSS_CFG_TBL_SIZE) + #define HCLGEVF_RSS_INPUT_TUPLE_OTHER GENMASK(3, 0) #define HCLGEVF_RSS_INPUT_TUPLE_SCTP GENMASK(4, 0) #define HCLGEVF_D_PORT_BIT BIT(0) @@ -217,7 +216,8 @@ struct hclgevf_rss_cfg { u32 hash_algo; u32 rss_size; u8 hw_tc_map; - u8 rss_indirection_tbl[HCLGEVF_RSS_IND_TBL_SIZE]; /* shadow table */ + /* shadow table */ + u8 *rss_indirection_tbl; struct hclgevf_rss_tuple_cfg rss_tuple_sets; };
From: GuoJia Liao liaoguojia@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 693e44157d31c5a347c55de19e59017fbf0f8b2e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
When update the TC info for NIC, there are some differences between PF and VF. Currently, four "vport->vport_id" are used to distinguish PF or VF. So merge them into one to improve readability and maintainability of code.
Signed-off-by: GuoJia Liao liaoguojia@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 -- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 ++ .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 15 ++++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 5a549194f205..2bbdaa396a95 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -55,8 +55,6 @@
#define HCLGE_LINK_STATUS_MS 10
-#define HCLGE_VF_VPORT_START_NUM 1 - static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps); static int hclge_init_vlan_config(struct hclge_dev *hdev); static void hclge_sync_vlan_filter(struct hclge_dev *hdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index a9c67e3891eb..a10a17c4c782 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -17,6 +17,8 @@
#define HCLGE_MAX_PF_NUM 8
+#define HCLGE_VF_VPORT_START_NUM 1 + #define HCLGE_RD_FIRST_STATS_NUM 2 #define HCLGE_RD_OTHER_STATS_NUM 4
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 216ab1e92723..906d98e515aa 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -640,13 +640,18 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) /* TC configuration is shared by PF/VF in one port, only allow * one tc for VF for simplicity. VF's vport_id is non zero. */ - kinfo->tc_info.num_tc = vport->vport_id ? 1 : + if (vport->vport_id) { + kinfo->tc_info.num_tc = 1; + vport->qs_offset = HNAE3_MAX_TC + + vport->vport_id - HCLGE_VF_VPORT_START_NUM; + vport_max_rss_size = hdev->vf_rss_size_max; + } else { + kinfo->tc_info.num_tc = min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); - vport->qs_offset = (vport->vport_id ? HNAE3_MAX_TC : 0) + - (vport->vport_id ? (vport->vport_id - 1) : 0); + vport->qs_offset = 0; + vport_max_rss_size = hdev->pf_rss_size_max; + }
- vport_max_rss_size = vport->vport_id ? hdev->vf_rss_size_max : - hdev->pf_rss_size_max; max_rss_size = min_t(u16, vport_max_rss_size, hclge_vport_get_max_rss_size(vport));
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit e070c8b91ac1c7810c8448b1e5534d1895a0c7f4 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Since the newer hardware may supports different frame size, so add support to obtain the capability from the firmware instead of the fixed value.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +-- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 5 ++--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 3 ++- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +++++- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 3 ++- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++++ drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 2 ++ 9 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 0e4e18a10413..583126143a8f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -283,6 +283,7 @@ struct hnae3_dev_specs { u16 int_ql_max; /* max value of interrupt coalesce based on INT_QL */ u16 max_int_gl; /* max value of interrupt coalesce based on INT_GL */ u8 max_non_tso_bd_num; /* max BD number of one non-TSO packet */ + u16 max_frm_size; };
struct hnae3_client_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index c5958754f939..4f7922a1fa7c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -389,6 +389,7 @@ static void hns3_dbg_dev_specs(struct hnae3_handle *h) kinfo->tc_info.num_tc); dev_info(priv->dev, "MAX INT QL: %u\n", dev_specs->int_ql_max); dev_info(priv->dev, "MAX INT GL: %u\n", dev_specs->max_int_gl); + dev_info(priv->dev, "MAX frame size: %u\n", dev_specs->max_frm_size); }
static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index affee064c986..e509afda2526 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4306,8 +4306,7 @@ static int hns3_client_init(struct hnae3_handle *handle)
hns3_dbg_init(handle);
- /* MTU range: (ETH_MIN_MTU(kernel default) - 9702) */ - netdev->max_mtu = HNS3_MAX_MTU; + netdev->max_mtu = HNS3_MAX_MTU(ae_dev->dev_specs.max_frm_size);
if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps)) set_bit(HNS3_NIC_STATE_HW_TX_CSUM_ENABLE, &priv->state); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 0b531e107e26..fdf552a4b662 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -56,9 +56,8 @@ enum hns3_nic_state { #define HNS3_RING_MIN_PENDING 72 #define HNS3_RING_BD_MULTIPLE 8 /* max frame size of mac */ -#define HNS3_MAC_MAX_FRAME 9728 -#define HNS3_MAX_MTU \ - (HNS3_MAC_MAX_FRAME - (ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN)) +#define HNS3_MAX_MTU(max_frm_size) \ + ((max_frm_size) - (ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN))
#define HNS3_BD_SIZE_512_TYPE 0 #define HNS3_BD_SIZE_1024_TYPE 1 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 2bbb569aee55..433dec1d0e8c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -1131,7 +1131,8 @@ struct hclge_dev_specs_0_cmd { #define HCLGE_DEF_MAX_INT_GL 0x1FE0U
struct hclge_dev_specs_1_cmd { - __le32 rsv0; + __le16 max_frm_size; + __le16 rsv0; __le16 max_int_gl; u8 rsv1[18]; }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2bbdaa396a95..0e2d5c983504 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1371,6 +1371,7 @@ static void hclge_set_default_dev_specs(struct hclge_dev *hdev) ae_dev->dev_specs.rss_key_size = HCLGE_RSS_KEY_SIZE; ae_dev->dev_specs.max_tm_rate = HCLGE_ETHER_MAX_RATE; ae_dev->dev_specs.max_int_gl = HCLGE_DEF_MAX_INT_GL; + ae_dev->dev_specs.max_frm_size = HCLGE_MAC_MAX_FRAME; }
static void hclge_parse_dev_specs(struct hclge_dev *hdev, @@ -1390,6 +1391,7 @@ static void hclge_parse_dev_specs(struct hclge_dev *hdev, ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size); ae_dev->dev_specs.max_tm_rate = le32_to_cpu(req0->max_tm_rate); ae_dev->dev_specs.max_int_gl = le16_to_cpu(req1->max_int_gl); + ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size); }
static void hclge_check_dev_specs(struct hclge_dev *hdev) @@ -1406,6 +1408,8 @@ static void hclge_check_dev_specs(struct hclge_dev *hdev) dev_specs->max_tm_rate = HCLGE_ETHER_MAX_RATE; if (!dev_specs->max_int_gl) dev_specs->max_int_gl = HCLGE_DEF_MAX_INT_GL; + if (!dev_specs->max_frm_size) + dev_specs->max_frm_size = HCLGE_MAC_MAX_FRAME; }
static int hclge_query_dev_specs(struct hclge_dev *hdev) @@ -9672,7 +9676,7 @@ int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu) /* HW supprt 2 layer vlan */ max_frm_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN; if (max_frm_size < HCLGE_MAC_MIN_FRAME || - max_frm_size > HCLGE_MAC_MAX_FRAME) + max_frm_size > hdev->ae_dev->dev_specs.max_frm_size) return -EINVAL;
max_frm_size = max(max_frm_size, HCLGE_MAC_DEFAULT_FRAME); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index d591b33a5698..ac2864a7ce8d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -296,7 +296,8 @@ struct hclgevf_dev_specs_0_cmd { #define HCLGEVF_DEF_MAX_INT_GL 0x1FE0U
struct hclgevf_dev_specs_1_cmd { - __le32 rsv0; + __le16 max_frm_size; + __le16 rsv0; __le16 max_int_gl; u8 rsv1[18]; }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 090591e3f087..ac527003478c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -3058,6 +3058,7 @@ static void hclgevf_set_default_dev_specs(struct hclgevf_dev *hdev) ae_dev->dev_specs.rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE; ae_dev->dev_specs.rss_key_size = HCLGEVF_RSS_KEY_SIZE; ae_dev->dev_specs.max_int_gl = HCLGEVF_DEF_MAX_INT_GL; + ae_dev->dev_specs.max_frm_size = HCLGEVF_MAC_MAX_FRAME; }
static void hclgevf_parse_dev_specs(struct hclgevf_dev *hdev, @@ -3076,6 +3077,7 @@ static void hclgevf_parse_dev_specs(struct hclgevf_dev *hdev, ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max); ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size); ae_dev->dev_specs.max_int_gl = le16_to_cpu(req1->max_int_gl); + ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size); }
static void hclgevf_check_dev_specs(struct hclgevf_dev *hdev) @@ -3090,6 +3092,8 @@ static void hclgevf_check_dev_specs(struct hclgevf_dev *hdev) dev_specs->rss_key_size = HCLGEVF_RSS_KEY_SIZE; if (!dev_specs->max_int_gl) dev_specs->max_int_gl = HCLGEVF_DEF_MAX_INT_GL; + if (!dev_specs->max_frm_size) + dev_specs->max_frm_size = HCLGEVF_MAC_MAX_FRAME; }
static int hclgevf_query_dev_specs(struct hclgevf_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 6147bd74d4a2..8c27ecd819af 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -124,6 +124,8 @@ #define HCLGEVF_RSS_INPUT_TUPLE_SCTP_NO_PORT \ (HCLGEVF_D_IP_BIT | HCLGEVF_S_IP_BIT | HCLGEVF_V_TAG_BIT)
+#define HCLGEVF_MAC_MAX_FRAME 9728 + #define HCLGEVF_STATS_TIMER_INTERVAL 36U
enum hclgevf_evt_cause {
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 2783e77b8df96aea2a5719af19b5f85e89d91982 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
In order to add a method to check the specification of max tm rate for debugging, function hns3_dbg_dev_specs() adds this value print.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 4f7922a1fa7c..d88fc3c7f872 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -390,6 +390,7 @@ static void hns3_dbg_dev_specs(struct hnae3_handle *h) dev_info(priv->dev, "MAX INT QL: %u\n", dev_specs->int_ql_max); dev_info(priv->dev, "MAX INT GL: %u\n", dev_specs->max_int_gl); dev_info(priv->dev, "MAX frame size: %u\n", dev_specs->max_frm_size); + dev_info(priv->dev, "MAX TM RATE: %uMbps\n", dev_specs->max_tm_rate); }
static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer,
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 3f094bd11a3720d2a00e9b6dfc53f1ab25884a49 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The max qset number is a fixed value now and it is defined by a macro. In order to support other value in different kinds of device, it is better to use specification queried from firmware to replace macro.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 1 + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 8 +++----- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 ++ 6 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 583126143a8f..769e2cdb3e34 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -284,6 +284,7 @@ struct hnae3_dev_specs { u16 max_int_gl; /* max value of interrupt coalesce based on INT_GL */ u8 max_non_tso_bd_num; /* max BD number of one non-TSO packet */ u16 max_frm_size; + u16 max_qset_num; };
struct hnae3_client_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index d88fc3c7f872..36c7813b5996 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -391,6 +391,7 @@ static void hns3_dbg_dev_specs(struct hnae3_handle *h) dev_info(priv->dev, "MAX INT GL: %u\n", dev_specs->max_int_gl); dev_info(priv->dev, "MAX frame size: %u\n", dev_specs->max_frm_size); dev_info(priv->dev, "MAX TM RATE: %uMbps\n", dev_specs->max_tm_rate); + dev_info(priv->dev, "MAX QSET number: %u\n", dev_specs->max_qset_num); }
static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 433dec1d0e8c..a7176ef5843e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -1132,7 +1132,7 @@ struct hclge_dev_specs_0_cmd {
struct hclge_dev_specs_1_cmd { __le16 max_frm_size; - __le16 rsv0; + __le16 max_qset_num; __le16 max_int_gl; u8 rsv1[18]; }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 8f3fefe50719..113efd4ae157 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1599,8 +1599,6 @@ static void hclge_dbg_dump_qs_shaper_all(struct hclge_dev *hdev) static void hclge_dbg_dump_qs_shaper(struct hclge_dev *hdev, const char *cmd_buf) { -#define HCLGE_MAX_QSET_NUM 1024 - u16 qsid; int ret;
@@ -1610,9 +1608,9 @@ static void hclge_dbg_dump_qs_shaper(struct hclge_dev *hdev, return; }
- if (qsid >= HCLGE_MAX_QSET_NUM) { - dev_err(&hdev->pdev->dev, "qsid(%u) out of range[0-1023]\n", - qsid); + if (qsid >= hdev->ae_dev->dev_specs.max_qset_num) { + dev_err(&hdev->pdev->dev, "qsid(%u) out of range[0-%u]\n", + qsid, hdev->ae_dev->dev_specs.max_qset_num - 1); return; }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 0e2d5c983504..ffb88e157540 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1372,6 +1372,7 @@ static void hclge_set_default_dev_specs(struct hclge_dev *hdev) ae_dev->dev_specs.max_tm_rate = HCLGE_ETHER_MAX_RATE; ae_dev->dev_specs.max_int_gl = HCLGE_DEF_MAX_INT_GL; ae_dev->dev_specs.max_frm_size = HCLGE_MAC_MAX_FRAME; + ae_dev->dev_specs.max_qset_num = HCLGE_MAX_QSET_NUM; }
static void hclge_parse_dev_specs(struct hclge_dev *hdev, @@ -1390,6 +1391,7 @@ static void hclge_parse_dev_specs(struct hclge_dev *hdev, ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max); ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size); ae_dev->dev_specs.max_tm_rate = le32_to_cpu(req0->max_tm_rate); + ae_dev->dev_specs.max_qset_num = le16_to_cpu(req1->max_qset_num); ae_dev->dev_specs.max_int_gl = le16_to_cpu(req1->max_int_gl); ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size); } @@ -1406,6 +1408,8 @@ static void hclge_check_dev_specs(struct hclge_dev *hdev) dev_specs->rss_key_size = HCLGE_RSS_KEY_SIZE; if (!dev_specs->max_tm_rate) dev_specs->max_tm_rate = HCLGE_ETHER_MAX_RATE; + if (!dev_specs->max_qset_num) + dev_specs->max_qset_num = HCLGE_MAX_QSET_NUM; if (!dev_specs->max_int_gl) dev_specs->max_int_gl = HCLGE_DEF_MAX_INT_GL; if (!dev_specs->max_frm_size) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index a10a17c4c782..33b17a199e18 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -148,6 +148,8 @@ /* Factor used to calculate offset and bitmap of VF num */ #define HCLGE_VF_NUM_PER_CMD 64
+#define HCLGE_MAX_QSET_NUM 1024 + enum HLCGE_PORT_TYPE { HOST_PORT, NETWORK_PORT
From: Yonglong Liu liuyonglong@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 0256844d0f325c323baf947eaf6bb375d195de26 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
queue_id, qset_id and other IDs are unsigned type, so modify the corresponding local variables' type in hclge_dbg_dump_tm_map() from signed to unsigned. kstrtouint() and the print format should be updated as well.
Signed-off-by: Yonglong Liu liuyonglong@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 113efd4ae157..a0a33c02ce25 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -696,17 +696,16 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, u32 qset_mapping[HCLGE_BP_EXT_GRP_NUM]; struct hclge_qs_to_pri_link_cmd *map; struct hclge_tqp_tx_queue_tc_cmd *tc; + u16 group_id, queue_id, qset_id; enum hclge_opcode_type cmd; + u8 grp_num, pri_id, tc_id; struct hclge_desc desc; - int queue_id, group_id; - int tc_id, qset_id; - int pri_id, ret; u16 qs_id_l; u16 qs_id_h; - u8 grp_num; + int ret; u32 i;
- ret = kstrtouint(cmd_buf, 0, &queue_id); + ret = kstrtou16(cmd_buf, 0, &queue_id); queue_id = (ret != 0) ? 0 : queue_id;
cmd = HCLGE_OPC_TM_NQ_TO_QS_LINK; @@ -754,7 +753,7 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, tc_id = tc->tc_id & 0x7;
dev_info(&hdev->pdev->dev, "queue_id | qset_id | pri_id | tc_id\n"); - dev_info(&hdev->pdev->dev, "%04d | %04d | %02d | %02d\n", + dev_info(&hdev->pdev->dev, "%04u | %04u | %02u | %02u\n", queue_id, qset_id, pri_id, tc_id);
if (!hnae3_dev_dcb_supported(hdev)) {
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit ae9e492a366433b97be414d2e90a2e24f8446abf category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Since the real tx queue number and real rx queue number always be updated when netdev opens, it's redundant to call hclge_client_setup_tc to do the same thing. So remove it.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 - .../net/ethernet/hisilicon/hns3/hns3_enet.c | 15 ----------- .../hisilicon/hns3/hns3pf/hclge_dcb.c | 27 ------------------- 3 files changed, 43 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 769e2cdb3e34..ab52a1fb35e5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -291,7 +291,6 @@ struct hnae3_client_ops { int (*init_instance)(struct hnae3_handle *handle); void (*uninit_instance)(struct hnae3_handle *handle, bool reset); void (*link_status_change)(struct hnae3_handle *handle, bool state); - int (*setup_tc)(struct hnae3_handle *handle, u8 tc); int (*reset_notify)(struct hnae3_handle *handle, enum hnae3_reset_notify_type type); void (*process_hw_error)(struct hnae3_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index e509afda2526..1a4d24abd486 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4409,20 +4409,6 @@ static void hns3_link_status_change(struct hnae3_handle *handle, bool linkup) } }
-static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) -{ - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct net_device *ndev = kinfo->netdev; - - if (tc > HNAE3_MAX_TC) - return -EINVAL; - - if (!ndev) - return -ENODEV; - - return hns3_nic_set_real_num_queue(ndev); -} - static void hns3_clear_tx_ring(struct hns3_enet_ring *ring) { while (ring->next_to_clean != ring->next_to_use) { @@ -4864,7 +4850,6 @@ static const struct hnae3_client_ops client_ops = { .init_instance = hns3_client_init, .uninit_instance = hns3_client_uninit, .link_status_change = hns3_link_status_change, - .setup_tc = hns3_client_setup_tc, .reset_notify = hns3_reset_notify, .process_hw_error = hns3_process_hw_error, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index e08d11b8ecf1..5bf5db91d16c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -176,29 +176,6 @@ static int hclge_map_update(struct hclge_dev *hdev) return hclge_rss_init_hw(hdev); }
-static int hclge_client_setup_tc(struct hclge_dev *hdev) -{ - struct hclge_vport *vport = hdev->vport; - struct hnae3_client *client; - struct hnae3_handle *handle; - int ret; - u32 i; - - for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - handle = &vport[i].nic; - client = handle->client; - - if (!client || !client->ops || !client->ops->setup_tc) - continue; - - ret = client->ops->setup_tc(handle, hdev->tm_info.num_tc); - if (ret) - return ret; - } - - return 0; -} - static int hclge_notify_down_uinit(struct hclge_dev *hdev) { int ret; @@ -257,10 +234,6 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) if (ret) goto err_out;
- ret = hclge_client_setup_tc(hdev); - if (ret) - goto err_out; - ret = hclge_notify_init_up(hdev); if (ret) return ret;
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 9d2a1cea6997ecd4f05833dfffb9907ffaa41bf5 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To make the code more readable, this patch adds a definition for the magic number 126 used for the default shaper param ir_b, and rename macro DIVISOR_IR_B_126.
No functional change.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 906d98e515aa..151afd1f0688 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -41,8 +41,9 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, struct hclge_shaper_ir_para *ir_para, u32 max_tm_rate) { +#define DEFAULT_SHAPER_IR_B 126 #define DIVISOR_CLK (1000 * 8) -#define DIVISOR_IR_B_126 (126 * DIVISOR_CLK) +#define DEFAULT_DIVISOR_IR_B (DEFAULT_SHAPER_IR_B * DIVISOR_CLK)
static const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = { 6 * 256, /* Prioriy level */ @@ -69,10 +70,10 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, * ir_calc = ---------------- * 1000 * tick * 1 */ - ir_calc = (DIVISOR_IR_B_126 + (tick >> 1) - 1) / tick; + ir_calc = (DEFAULT_DIVISOR_IR_B + (tick >> 1) - 1) / tick;
if (ir_calc == ir) { - ir_para->ir_b = 126; + ir_para->ir_b = DEFAULT_SHAPER_IR_B; ir_para->ir_u = 0; ir_para->ir_s = 0;
@@ -81,7 +82,8 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, /* Increasing the denominator to select ir_s value */ while (ir_calc >= ir && ir) { ir_s_calc++; - ir_calc = DIVISOR_IR_B_126 / (tick * (1 << ir_s_calc)); + ir_calc = DEFAULT_DIVISOR_IR_B / + (tick * (1 << ir_s_calc)); }
ir_para->ir_b = (ir * tick * (1 << ir_s_calc) + @@ -92,12 +94,12 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
while (ir_calc < ir) { ir_u_calc++; - numerator = DIVISOR_IR_B_126 * (1 << ir_u_calc); + numerator = DEFAULT_DIVISOR_IR_B * (1 << ir_u_calc); ir_calc = (numerator + (tick >> 1)) / tick; }
if (ir_calc == ir) { - ir_para->ir_b = 126; + ir_para->ir_b = DEFAULT_SHAPER_IR_B; } else { u32 denominator = DIVISOR_CLK * (1 << --ir_u_calc); ir_para->ir_b = (ir * tick + (denominator >> 1)) /
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 9393eb5034a040931120f9c6eed9bf0e78029192 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
In macro definitions, parentheses are unnecessary in some cases, such as the calling parameter of a function, the left variable of the equal sign, and so on. So remove these unnecessary parentheses according to these rules.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 6 +++--- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 10 +++++----- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 4 ++-- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 6 +++--- .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index ab52a1fb35e5..406393990c7d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -271,7 +271,7 @@ struct hnae3_ring_chain_node { };
#define HNAE3_IS_TX_RING(node) \ - (((node)->flag & (1 << HNAE3_RING_TYPE_B)) == HNAE3_RING_TYPE_TX) + (((node)->flag & 1 << HNAE3_RING_TYPE_B) == HNAE3_RING_TYPE_TX)
/* device specification info from firmware */ struct hnae3_dev_specs { @@ -774,9 +774,9 @@ struct hnae3_handle { #define hnae3_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift))
#define hnae3_set_bit(origin, shift, val) \ - hnae3_set_field((origin), (0x1 << (shift)), (shift), (val)) + hnae3_set_field(origin, 0x1 << (shift), shift, val) #define hnae3_get_bit(origin, shift) \ - hnae3_get_field((origin), (0x1 << (shift)), (shift)) + hnae3_get_field(origin, 0x1 << (shift), shift)
#define HNAE3_DBG_TM_NODES "tm_nodes" #define HNAE3_DBG_TM_PRI "tm_priority" diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 1a4d24abd486..5b44a14dfe25 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -32,7 +32,7 @@ #define CREATE_TRACE_POINTS #include "hns3_trace.h"
-#define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift))) +#define hns3_set_field(origin, shift, val) ((origin) |= (val) << (shift)) #define hns3_tx_bd_count(S) DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE)
#define hns3_rl_err(fmt, ...) \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index fdf552a4b662..4e88d957a7d9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -556,7 +556,7 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value) }
#define hns3_read_dev(a, reg) \ - hns3_read_reg((a)->io_base, (reg)) + hns3_read_reg((a)->io_base, reg)
static inline bool hns3_nic_resetting(struct net_device *netdev) { @@ -566,7 +566,7 @@ static inline bool hns3_nic_resetting(struct net_device *netdev) }
#define hns3_write_dev(a, reg, value) \ - hns3_write_reg((a)->io_base, (reg), (value)) + hns3_write_reg((a)->io_base, reg, value)
#define ring_to_dev(ring) ((ring)->dev)
@@ -590,15 +590,15 @@ static inline unsigned int hns3_page_order(struct hns3_enet_ring *ring)
/* iterator for handling rings in ring group */ #define hns3_for_each_ring(pos, head) \ - for (pos = (head).ring; pos; pos = pos->next) + for (pos = (head).ring; (pos); pos = (pos)->next)
#define hns3_get_handle(ndev) \ (((struct hns3_nic_priv *)netdev_priv(ndev))->ae_handle)
-#define hns3_gl_usec_to_reg(int_gl) (int_gl >> 1) +#define hns3_gl_usec_to_reg(int_gl) ((int_gl) >> 1) #define hns3_gl_round_down(int_gl) round_down(int_gl, 2)
-#define hns3_rl_usec_to_reg(int_rl) (int_rl >> 2) +#define hns3_rl_usec_to_reg(int_rl) ((int_rl) >> 2) #define hns3_rl_round_down(int_rl) round_down(int_rl, 4)
void hns3_ethtool_set_ops(struct net_device *netdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index a7176ef5843e..057dda735492 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -1144,9 +1144,9 @@ static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value) }
#define hclge_write_dev(a, reg, value) \ - hclge_write_reg((a)->io_base, (reg), (value)) + hclge_write_reg((a)->io_base, reg, value) #define hclge_read_dev(a, reg) \ - hclge_read_reg((a)->io_base, (reg)) + hclge_read_reg((a)->io_base, reg)
static inline u32 hclge_read_reg(u8 __iomem *base, u32 reg) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index ffb88e157540..2852b054cdda 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -24,7 +24,7 @@ #include "hnae3.h"
#define HCLGE_NAME "hclge" -#define HCLGE_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset)))) +#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) #define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f))
#define HCLGE_BUF_SIZE_UNIT 256U diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 33b17a199e18..0d86c4d50489 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -728,7 +728,7 @@ struct hclge_vf_vlan_cfg { * x = (~k) & v * y = (k ^ ~v) & k */ -#define calc_x(x, k, v) ((x) = (~(k) & (v))) +#define calc_x(x, k, v) (x = ~(k) & (v)) #define calc_y(y, k, v) \ do { \ const typeof(k) _k_ = (k); \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index d33cb04acbef..b25d76023af0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -17,7 +17,7 @@
/* SP or DWRR */ #define HCLGE_TM_TX_SCHD_DWRR_MSK BIT(0) -#define HCLGE_TM_TX_SCHD_SP_MSK (0xFE) +#define HCLGE_TM_TX_SCHD_SP_MSK 0xFE
#define HCLGE_ETHER_MAX_RATE 100000
@@ -214,8 +214,8 @@ struct hclge_pri_shaper_para { (HCLGE_TM_SHAP_##string##_MSK), \ (HCLGE_TM_SHAP_##string##_LSH), val) #define hclge_tm_get_field(src, string) \ - hnae3_get_field((src), (HCLGE_TM_SHAP_##string##_MSK), \ - (HCLGE_TM_SHAP_##string##_LSH)) + hnae3_get_field((src), HCLGE_TM_SHAP_##string##_MSK, \ + HCLGE_TM_SHAP_##string##_LSH)
int hclge_tm_schd_init(struct hclge_dev *hdev); int hclge_tm_vport_map_update(struct hclge_dev *hdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index ac2864a7ce8d..cb619ccc5989 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -315,9 +315,9 @@ static inline u32 hclgevf_read_reg(u8 __iomem *base, u32 reg) }
#define hclgevf_write_dev(a, reg, value) \ - hclgevf_write_reg((a)->io_base, (reg), (value)) + hclgevf_write_reg((a)->io_base, reg, value) #define hclgevf_read_dev(a, reg) \ - hclgevf_read_reg((a)->io_base, (reg)) + hclgevf_read_reg((a)->io_base, reg)
#define HCLGEVF_SEND_SYNC(flag) \ ((flag) & HCLGEVF_CMD_FLAG_NO_INTR)
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit c5aaf1761883bbc02a8a158a0bc7a5950ad8542b category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Fix an issue where the formatting symbol of the formatting input and output function does not match the actual type.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +++--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 36c7813b5996..818ac2c7c7ea 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -162,7 +162,7 @@ static int hns3_dbg_queue_map(struct hnae3_handle *h) continue;
dev_info(&h->pdev->dev, - " %4d %4d %4d\n", + " %4d %4u %4d\n", i, global_qid, priv->ring[i].tqp_vector->vector_irq); }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 5b44a14dfe25..19e0a3639963 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2359,7 +2359,7 @@ static pci_ers_result_t hns3_error_detected(struct pci_dev *pdev, struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); pci_ers_result_t ret;
- dev_info(&pdev->dev, "PCI error detected, state(=%d)!!\n", state); + dev_info(&pdev->dev, "PCI error detected, state(=%u)!!\n", state);
if (state == pci_channel_io_perm_failure) return PCI_ERS_RESULT_DISCONNECT; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 6828432cb3be..d20f2e246017 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -458,7 +458,7 @@ static void *hns3_update_strings(u8 *data, const struct hns3_stats *stats, data[ETH_GSTRING_LEN - 1] = '\0';
/* first, prepend the prefix string */ - n1 = scnprintf(data, MAX_PREFIX_SIZE, "%s%d_", + n1 = scnprintf(data, MAX_PREFIX_SIZE, "%s%u_", prefix, i); size_left = (ETH_GSTRING_LEN - 1) - n1;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2852b054cdda..98c9cb14af5a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -626,7 +626,7 @@ static u8 *hclge_tqps_get_strings(struct hnae3_handle *handle, u8 *data) for (i = 0; i < kinfo->num_tqps; i++) { struct hclge_tqp *tqp = container_of(handle->kinfo.tqp[i], struct hclge_tqp, q); - snprintf(buff, ETH_GSTRING_LEN, "txq%d_pktnum_rcd", + snprintf(buff, ETH_GSTRING_LEN, "txq%u_pktnum_rcd", tqp->index); buff = buff + ETH_GSTRING_LEN; } @@ -634,7 +634,7 @@ static u8 *hclge_tqps_get_strings(struct hnae3_handle *handle, u8 *data) for (i = 0; i < kinfo->num_tqps; i++) { struct hclge_tqp *tqp = container_of(kinfo->tqp[i], struct hclge_tqp, q); - snprintf(buff, ETH_GSTRING_LEN, "rxq%d_pktnum_rcd", + snprintf(buff, ETH_GSTRING_LEN, "rxq%u_pktnum_rcd", tqp->index); buff = buff + ETH_GSTRING_LEN; } @@ -5595,7 +5595,7 @@ static int hclge_fd_check_ext_tuple(struct hclge_dev *hdev, if (fs->m_ext.vlan_tci && be16_to_cpu(fs->h_ext.vlan_tci) >= VLAN_N_VID) { dev_err(&hdev->pdev->dev, - "failed to config vlan_tci, invalid vlan_tci: %u, max is %u.\n", + "failed to config vlan_tci, invalid vlan_tci: %u, max is %d.\n", ntohs(fs->h_ext.vlan_tci), VLAN_N_VID - 1); return -EINVAL; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 73a6eaa940b7..9265a00de18e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -56,7 +56,7 @@ static int hclge_gen_resp_to_vf(struct hclge_vport *vport, resp_pf_to_vf->msg.resp_status = resp; } else { dev_warn(&hdev->pdev->dev, - "failed to send response to VF, response status %d is out-of-bound\n", + "failed to send response to VF, response status %u is out-of-bound\n", resp); resp_pf_to_vf->msg.resp_status = EIO; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index ac527003478c..cb86d211cf34 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -180,7 +180,7 @@ static u8 *hclgevf_tqps_get_strings(struct hnae3_handle *handle, u8 *data) for (i = 0; i < kinfo->num_tqps; i++) { struct hclgevf_tqp *tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q); - snprintf(buff, ETH_GSTRING_LEN, "txq%d_pktnum_rcd", + snprintf(buff, ETH_GSTRING_LEN, "txq%u_pktnum_rcd", tqp->index); buff += ETH_GSTRING_LEN; } @@ -188,7 +188,7 @@ static u8 *hclgevf_tqps_get_strings(struct hnae3_handle *handle, u8 *data) for (i = 0; i < kinfo->num_tqps; i++) { struct hclgevf_tqp *tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q); - snprintf(buff, ETH_GSTRING_LEN, "rxq%d_pktnum_rcd", + snprintf(buff, ETH_GSTRING_LEN, "rxq%u_pktnum_rcd", tqp->index); buff += ETH_GSTRING_LEN; }
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 6e7f109ee9d8ed94a8c403e4daf34e752602148b category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The type of parameters in hclge_parse_speed() should be unsigned type, so change them.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 98c9cb14af5a..33afd4ec37a4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -928,7 +928,7 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev) return 0; }
-static int hclge_parse_speed(int speed_cmd, int *speed) +static int hclge_parse_speed(u8 speed_cmd, u32 *speed) { switch (speed_cmd) { case 6:
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit cad8dfe82a9eb8d889cc550ceb8e61112376ae6f category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The type of parameter mpf_bd_num and pf_bd_num in hclge_query_bd_num() should be u32* instead of int*, so change them.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 3226ca176155..78d3eb142df8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1074,7 +1074,7 @@ static int hclge_config_ssu_hw_err_int(struct hclge_dev *hdev, bool en) * This function querys number of mpf and pf buffer descriptors. */ static int hclge_query_bd_num(struct hclge_dev *hdev, bool is_ras, - int *mpf_bd_num, int *pf_bd_num) + u32 *mpf_bd_num, u32 *pf_bd_num) { struct device *dev = &hdev->pdev->dev; u32 mpf_min_bd_num, pf_min_bd_num; @@ -1103,7 +1103,7 @@ static int hclge_query_bd_num(struct hclge_dev *hdev, bool is_ras, *mpf_bd_num = le32_to_cpu(desc_bd.data[0]); *pf_bd_num = le32_to_cpu(desc_bd.data[1]); if (*mpf_bd_num < mpf_min_bd_num || *pf_bd_num < pf_min_bd_num) { - dev_err(dev, "Invalid bd num: mpf(%d), pf(%d)\n", + dev_err(dev, "Invalid bd num: mpf(%u), pf(%u)\n", *mpf_bd_num, *pf_bd_num); return -EINVAL; }
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 64749c9c38a9b7f64b83b6970b679f2fb7cd6387 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Since hns3_uninit_all_ring() only returns 0, so remove this redundant return value and function declaration in hns3_enet.h.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 12 +++--------- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 1 - 2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 19e0a3639963..9c4b997486e3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4115,7 +4115,7 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv) return -ENOMEM; }
-int hns3_uninit_all_ring(struct hns3_nic_priv *priv) +static void hns3_uninit_all_ring(struct hns3_nic_priv *priv) { struct hnae3_handle *h = priv->ae_handle; int i; @@ -4124,7 +4124,6 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv) hns3_fini_ring(&priv->ring[i]); hns3_fini_ring(&priv->ring[i + h->kinfo.num_tqps]); } - return 0; }
/* Set mac addr if it is configured. or leave it to the AE driver */ @@ -4352,7 +4351,6 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset) { struct net_device *netdev = handle->kinfo.netdev; struct hns3_nic_priv *priv = netdev_priv(netdev); - int ret;
if (netdev->reg_state != NETREG_UNINITIALIZED) unregister_netdev(netdev); @@ -4378,9 +4376,7 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
hns3_nic_dealloc_vector_data(priv);
- ret = hns3_uninit_all_ring(priv); - if (ret) - netdev_err(netdev, "uninit ring error\n"); + hns3_uninit_all_ring(priv);
hns3_put_ring_config(priv);
@@ -4698,9 +4694,7 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
hns3_nic_dealloc_vector_data(priv);
- ret = hns3_uninit_all_ring(priv); - if (ret) - netdev_err(netdev, "uninit ring error\n"); + hns3_uninit_all_ring(priv);
hns3_put_ring_config(priv);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 4e88d957a7d9..e44224e23315 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -607,7 +607,6 @@ int hns3_set_channels(struct net_device *netdev,
void hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget); int hns3_init_all_ring(struct hns3_nic_priv *priv); -int hns3_uninit_all_ring(struct hns3_nic_priv *priv); int hns3_nic_reset_all_ring(struct hnae3_handle *h); void hns3_fini_ring(struct hns3_enet_ring *ring); netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 11ef971f5a6a35cf3bb4d67f0e1e38e0b6eb4f47 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Parameter vf in hclge_vf_rate_param_check() is unused now, so remove it.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 33afd4ec37a4..f44ae1b228fd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -10837,7 +10837,7 @@ static void hclge_reset_vf_rate(struct hclge_dev *hdev) } }
-static int hclge_vf_rate_param_check(struct hclge_dev *hdev, int vf, +static int hclge_vf_rate_param_check(struct hclge_dev *hdev, int min_tx_rate, int max_tx_rate) { if (min_tx_rate != 0 || @@ -10858,7 +10858,7 @@ static int hclge_set_vf_rate(struct hnae3_handle *handle, int vf, struct hclge_dev *hdev = vport->back; int ret;
- ret = hclge_vf_rate_param_check(hdev, vf, min_tx_rate, max_tx_rate); + ret = hclge_vf_rate_param_check(hdev, min_tx_rate, max_tx_rate); if (ret) return ret;
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 7ceb40b8207ea4aefed96c6dd22625b93aa121f9 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Some macros are defined but unused, so remove them.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 3 --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 1 - 2 files changed, 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 0d86c4d50489..19d7f28773f3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -46,15 +46,12 @@ #define HCLGE_CMDQ_RX_DEPTH_REG 0x27020 #define HCLGE_CMDQ_RX_TAIL_REG 0x27024 #define HCLGE_CMDQ_RX_HEAD_REG 0x27028 -#define HCLGE_CMDQ_INTR_SRC_REG 0x27100 #define HCLGE_CMDQ_INTR_STS_REG 0x27104 #define HCLGE_CMDQ_INTR_EN_REG 0x27108 #define HCLGE_CMDQ_INTR_GEN_REG 0x2710C
/* bar registers for common func */ #define HCLGE_VECTOR0_OTER_EN_REG 0x20600 -#define HCLGE_RAS_OTHER_STS_REG 0x20B00 -#define HCLGE_FUNC_RESET_STS_REG 0x20C00 #define HCLGE_GRO_EN_REG 0x28000
/* bar registers for rcb */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index cb619ccc5989..2a6aaffb9e9a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -278,7 +278,6 @@ struct hclgevf_cfg_tx_queue_pointer_cmd {
#define HCLGEVF_NIC_CMQ_DESC_NUM 1024 #define HCLGEVF_NIC_CMQ_DESC_NUM_S 3 -#define HCLGEVF_NIC_CMDQ_INT_SRC_REG 0x27100
#define HCLGEVF_QUERY_DEV_SPECS_BD_NUM 4
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 55ff3ed57b5031c3d48aa064333c35c6a547e3ee category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently the RSS commands of VF are using host byte order. According to the user manual, it should use little endian in the command to firmware. For the host and firmware are both using little endian, so it can work well in this case.
Do cleanup to make it more explicitly.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 6 +++--- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 15 ++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 2a6aaffb9e9a..8a37a22a176b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -216,8 +216,8 @@ struct hclgevf_rss_input_tuple_cmd { #define HCLGEVF_RSS_CFG_TBL_SIZE 16
struct hclgevf_rss_indirection_table_cmd { - u16 start_table_index; - u16 rss_set_bitmap; + __le16 start_table_index; + __le16 rss_set_bitmap; u8 rsv[4]; u8 rss_result[HCLGEVF_RSS_CFG_TBL_SIZE]; }; @@ -229,7 +229,7 @@ struct hclgevf_rss_indirection_table_cmd { #define HCLGEVF_RSS_TC_VALID_B 15 #define HCLGEVF_MAX_TC_NUM 8 struct hclgevf_rss_tc_mode_cmd { - u16 rss_tc_mode[HCLGEVF_MAX_TC_NUM]; + __le16 rss_tc_mode[HCLGEVF_MAX_TC_NUM]; u8 rsv[8]; };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index cb86d211cf34..a345307de590 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -658,8 +658,9 @@ static int hclgevf_set_rss_indir_table(struct hclgevf_dev *hdev) for (i = 0; i < rss_cfg_tbl_num; i++) { hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INDIR_TABLE, false); - req->start_table_index = i * HCLGEVF_RSS_CFG_TBL_SIZE; - req->rss_set_bitmap = HCLGEVF_RSS_SET_BITMAP_MSK; + req->start_table_index = + cpu_to_le16(i * HCLGEVF_RSS_CFG_TBL_SIZE); + req->rss_set_bitmap = cpu_to_le16(HCLGEVF_RSS_SET_BITMAP_MSK); for (j = 0; j < HCLGEVF_RSS_CFG_TBL_SIZE; j++) req->rss_result[j] = indir[i * HCLGEVF_RSS_CFG_TBL_SIZE + j]; @@ -700,12 +701,16 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size)
hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_TC_MODE, false); for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) { - hnae3_set_bit(req->rss_tc_mode[i], HCLGEVF_RSS_TC_VALID_B, + u16 mode = 0; + + hnae3_set_bit(mode, HCLGEVF_RSS_TC_VALID_B, (tc_valid[i] & 0x1)); - hnae3_set_field(req->rss_tc_mode[i], HCLGEVF_RSS_TC_SIZE_M, + hnae3_set_field(mode, HCLGEVF_RSS_TC_SIZE_M, HCLGEVF_RSS_TC_SIZE_S, tc_size[i]); - hnae3_set_field(req->rss_tc_mode[i], HCLGEVF_RSS_TC_OFFSET_M, + hnae3_set_field(mode, HCLGEVF_RSS_TC_OFFSET_M, HCLGEVF_RSS_TC_OFFSET_S, tc_offset[i]); + + req->rss_tc_mode[i] = cpu_to_le16(mode); } status = hclgevf_cmd_send(&hdev->hw, &desc, 1); if (status)
From: "Gustavo A. R. Silva" gustavoars@kernel.org
mainline inclusion from mainline-v5.12-rc1-dontuse commit 205238f4ed3e14aed07a7b0121b94e404e65e78c category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, a random stack value is being returned because variable _ret_ is not properly initialized. This variable is actually not used anymore and it should be removed.
Fix this by removing all instances of variable ret and return 0.
Fixes: 64749c9c38a9 ("net: hns3: remove redundant return value of hns3_uninit_all_ring()") Addresses-Coverity-ID: 1501700 ("Uninitialized scalar variable") Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9c4b997486e3..aa9870b255c6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4676,7 +4676,6 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) { struct net_device *netdev = handle->kinfo.netdev; struct hns3_nic_priv *priv = netdev_priv(netdev); - int ret;
if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) { netdev_warn(netdev, "already uninitialized\n"); @@ -4698,7 +4697,7 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
hns3_put_ring_config(priv);
- return ret; + return 0; }
static int hns3_reset_notify(struct hnae3_handle *handle,
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 1c9a98b0ba1f16490ea0d492a1cd606f3a4b1bee category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To improve code readability and maintainability, refactor hclge_cmd_convert_err_code() with an array of imp_errcode and common_errno mapping, instead of a bloated switch/case.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 6546b47bef88..cb2c955ce52c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -189,36 +189,35 @@ static bool hclge_is_special_opcode(u16 opcode) return false; }
+struct errcode { + u32 imp_errcode; + int common_errno; +}; + static int hclge_cmd_convert_err_code(u16 desc_ret) { - switch (desc_ret) { - case HCLGE_CMD_EXEC_SUCCESS: - return 0; - case HCLGE_CMD_NO_AUTH: - return -EPERM; - case HCLGE_CMD_NOT_SUPPORTED: - return -EOPNOTSUPP; - case HCLGE_CMD_QUEUE_FULL: - return -EXFULL; - case HCLGE_CMD_NEXT_ERR: - return -ENOSR; - case HCLGE_CMD_UNEXE_ERR: - return -ENOTBLK; - case HCLGE_CMD_PARA_ERR: - return -EINVAL; - case HCLGE_CMD_RESULT_ERR: - return -ERANGE; - case HCLGE_CMD_TIMEOUT: - return -ETIME; - case HCLGE_CMD_HILINK_ERR: - return -ENOLINK; - case HCLGE_CMD_QUEUE_ILLEGAL: - return -ENXIO; - case HCLGE_CMD_INVALID: - return -EBADR; - default: - return -EIO; - } + struct errcode hclge_cmd_errcode[] = { + {HCLGE_CMD_EXEC_SUCCESS, 0}, + {HCLGE_CMD_NO_AUTH, -EPERM}, + {HCLGE_CMD_NOT_SUPPORTED, -EOPNOTSUPP}, + {HCLGE_CMD_QUEUE_FULL, -EXFULL}, + {HCLGE_CMD_NEXT_ERR, -ENOSR}, + {HCLGE_CMD_UNEXE_ERR, -ENOTBLK}, + {HCLGE_CMD_PARA_ERR, -EINVAL}, + {HCLGE_CMD_RESULT_ERR, -ERANGE}, + {HCLGE_CMD_TIMEOUT, -ETIME}, + {HCLGE_CMD_HILINK_ERR, -ENOLINK}, + {HCLGE_CMD_QUEUE_ILLEGAL, -ENXIO}, + {HCLGE_CMD_INVALID, -EBADR}, + }; + u32 errcode_count = ARRAY_SIZE(hclge_cmd_errcode); + u32 i; + + for (i = 0; i < errcode_count; i++) + if (hclge_cmd_errcode[i].imp_errcode == desc_ret) + return hclge_cmd_errcode[i].common_errno; + + return -EIO; }
static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc,
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 433e2802775c370604b74378c00977b86623fa12 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To improve code readability and maintainability, refactor hclgevf_cmd_convert_err_code() with an array of imp_errcode and common_errno mapping, instead of a bloated switch/case.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3vf/hclgevf_cmd.c | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 0f93c2dd890d..603665e5bf39 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -176,36 +176,35 @@ void hclgevf_cmd_setup_basic_desc(struct hclgevf_desc *desc, desc->flag &= cpu_to_le16(~HCLGEVF_CMD_FLAG_WR); }
+struct vf_errcode { + u32 imp_errcode; + int common_errno; +}; + static int hclgevf_cmd_convert_err_code(u16 desc_ret) { - switch (desc_ret) { - case HCLGEVF_CMD_EXEC_SUCCESS: - return 0; - case HCLGEVF_CMD_NO_AUTH: - return -EPERM; - case HCLGEVF_CMD_NOT_SUPPORTED: - return -EOPNOTSUPP; - case HCLGEVF_CMD_QUEUE_FULL: - return -EXFULL; - case HCLGEVF_CMD_NEXT_ERR: - return -ENOSR; - case HCLGEVF_CMD_UNEXE_ERR: - return -ENOTBLK; - case HCLGEVF_CMD_PARA_ERR: - return -EINVAL; - case HCLGEVF_CMD_RESULT_ERR: - return -ERANGE; - case HCLGEVF_CMD_TIMEOUT: - return -ETIME; - case HCLGEVF_CMD_HILINK_ERR: - return -ENOLINK; - case HCLGEVF_CMD_QUEUE_ILLEGAL: - return -ENXIO; - case HCLGEVF_CMD_INVALID: - return -EBADR; - default: - return -EIO; - } + struct vf_errcode hclgevf_cmd_errcode[] = { + {HCLGEVF_CMD_EXEC_SUCCESS, 0}, + {HCLGEVF_CMD_NO_AUTH, -EPERM}, + {HCLGEVF_CMD_NOT_SUPPORTED, -EOPNOTSUPP}, + {HCLGEVF_CMD_QUEUE_FULL, -EXFULL}, + {HCLGEVF_CMD_NEXT_ERR, -ENOSR}, + {HCLGEVF_CMD_UNEXE_ERR, -ENOTBLK}, + {HCLGEVF_CMD_PARA_ERR, -EINVAL}, + {HCLGEVF_CMD_RESULT_ERR, -ERANGE}, + {HCLGEVF_CMD_TIMEOUT, -ETIME}, + {HCLGEVF_CMD_HILINK_ERR, -ENOLINK}, + {HCLGEVF_CMD_QUEUE_ILLEGAL, -ENXIO}, + {HCLGEVF_CMD_INVALID, -EBADR}, + }; + u32 errcode_count = ARRAY_SIZE(hclgevf_cmd_errcode); + u32 i; + + for (i = 0; i < errcode_count; i++) + if (hclgevf_cmd_errcode[i].imp_errcode == desc_ret) + return hclgevf_cmd_errcode[i].common_errno; + + return -EIO; }
/* hclgevf_cmd_send - send command to command queue
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit c318af3f568406a7a07194bf36c18d2053044ab4 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
As more commands are added, hns3_dbg_cmd_write() is going to get more bloated, so move the part about command check into a separate function.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 818ac2c7c7ea..dd11c57027bb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -423,6 +423,30 @@ static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, return (*ppos = len); }
+static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf) +{ + int ret = 0; + + if (strncmp(cmd_buf, "help", 4) == 0) + hns3_dbg_help(handle); + else if (strncmp(cmd_buf, "queue info", 10) == 0) + ret = hns3_dbg_queue_info(handle, cmd_buf); + else if (strncmp(cmd_buf, "queue map", 9) == 0) + ret = hns3_dbg_queue_map(handle); + else if (strncmp(cmd_buf, "bd info", 7) == 0) + ret = hns3_dbg_bd_info(handle, cmd_buf); + else if (strncmp(cmd_buf, "dev capability", 14) == 0) + hns3_dbg_dev_caps(handle); + else if (strncmp(cmd_buf, "dev spec", 8) == 0) + hns3_dbg_dev_specs(handle); + else if (handle->ae_algo->ops->dbg_run_cmd) + ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); + else + ret = -EOPNOTSUPP; + + return ret; +} + static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { @@ -430,7 +454,7 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, struct hns3_nic_priv *priv = handle->priv; char *cmd_buf, *cmd_buf_tmp; int uncopied_bytes; - int ret = 0; + int ret;
if (*ppos != 0) return 0; @@ -461,23 +485,7 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, count = cmd_buf_tmp - cmd_buf + 1; }
- if (strncmp(cmd_buf, "help", 4) == 0) - hns3_dbg_help(handle); - else if (strncmp(cmd_buf, "queue info", 10) == 0) - ret = hns3_dbg_queue_info(handle, cmd_buf); - else if (strncmp(cmd_buf, "queue map", 9) == 0) - ret = hns3_dbg_queue_map(handle); - else if (strncmp(cmd_buf, "bd info", 7) == 0) - ret = hns3_dbg_bd_info(handle, cmd_buf); - else if (strncmp(cmd_buf, "dev capability", 14) == 0) - hns3_dbg_dev_caps(handle); - else if (strncmp(cmd_buf, "dev spec", 8) == 0) - hns3_dbg_dev_specs(handle); - else if (handle->ae_algo->ops->dbg_run_cmd) - ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); - else - ret = -EOPNOTSUPP; - + ret = hns3_dbg_check_cmd(handle, cmd_buf); if (ret) hns3_dbg_help(handle);
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit eaede835675cbae3b84309255f81e9a5e1b502a2 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Use common ipv6_addr_any() to determine if an addr is ipv6 any addr.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index f44ae1b228fd..5bbe3035a3ff 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -13,6 +13,7 @@ #include <linux/platform_device.h> #include <linux/if_vlan.h> #include <linux/crash_dump.h> +#include <net/ipv6.h> #include <net/rtnetlink.h> #include "hclge_cmd.h" #include "hclge_dcb.h" @@ -5508,12 +5509,10 @@ static int hclge_fd_check_tcpip6_tuple(struct ethtool_tcpip6_spec *spec, BIT(INNER_IP_TOS);
/* check whether src/dst ip address used */ - if (!spec->ip6src[0] && !spec->ip6src[1] && - !spec->ip6src[2] && !spec->ip6src[3]) + if (ipv6_addr_any((struct in6_addr *)spec->ip6src)) *unused_tuple |= BIT(INNER_SRC_IP);
- if (!spec->ip6dst[0] && !spec->ip6dst[1] && - !spec->ip6dst[2] && !spec->ip6dst[3]) + if (ipv6_addr_any((struct in6_addr *)spec->ip6dst)) *unused_tuple |= BIT(INNER_DST_IP);
if (!spec->psrc) @@ -5538,12 +5537,10 @@ static int hclge_fd_check_ip6_tuple(struct ethtool_usrip6_spec *spec, BIT(INNER_IP_TOS) | BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT);
/* check whether src/dst ip address used */ - if (!spec->ip6src[0] && !spec->ip6src[1] && - !spec->ip6src[2] && !spec->ip6src[3]) + if (ipv6_addr_any((struct in6_addr *)spec->ip6src)) *unused_tuple |= BIT(INNER_SRC_IP);
- if (!spec->ip6dst[0] && !spec->ip6dst[1] && - !spec->ip6dst[2] && !spec->ip6dst[3]) + if (ipv6_addr_any((struct in6_addr *)spec->ip6dst)) *unused_tuple |= BIT(INNER_DST_IP);
if (!spec->l4_proto)
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 88936e320c1a9971b6b78a38e6bf737e43744f5e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To improve code readability and maintainability, separate the command handling part and the status parsing part from bloated hclge_set_vf_vlan_common().
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 73 ++++++++++++------- 1 file changed, 48 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 5bbe3035a3ff..d7a8adc8d6d9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8785,32 +8785,16 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) handle->netdev_flags &= ~HNAE3_VLAN_FLTR; }
-static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid, - bool is_kill, u16 vlan, - __be16 proto) +static int hclge_set_vf_vlan_filter_cmd(struct hclge_dev *hdev, u16 vfid, + bool is_kill, u16 vlan, + struct hclge_desc *desc) { - struct hclge_vport *vport = &hdev->vport[vfid]; struct hclge_vlan_filter_vf_cfg_cmd *req0; struct hclge_vlan_filter_vf_cfg_cmd *req1; - struct hclge_desc desc[2]; u8 vf_byte_val; u8 vf_byte_off; int ret;
- /* if vf vlan table is full, firmware will close vf vlan filter, it - * is unable and unnecessary to add new vlan id to vf vlan filter. - * If spoof check is enable, and vf vlan is full, it shouldn't add - * new vlan, because tx packets with these vlan id will be dropped. - */ - if (test_bit(vfid, hdev->vf_vlan_full) && !is_kill) { - if (vport->vf_info.spoofchk && vlan) { - dev_err(&hdev->pdev->dev, - "Can't add vlan due to spoof check is on and vf vlan table is full\n"); - return -EPERM; - } - return 0; - } - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_VLAN_FILTER_VF_CFG, false); hclge_cmd_setup_basic_desc(&desc[1], @@ -8840,12 +8824,22 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid, return ret; }
+ return 0; +} + +static int hclge_check_vf_vlan_cmd_status(struct hclge_dev *hdev, u16 vfid, + bool is_kill, struct hclge_desc *desc) +{ + struct hclge_vlan_filter_vf_cfg_cmd *req; + + req = (struct hclge_vlan_filter_vf_cfg_cmd *)desc[0].data; + if (!is_kill) { #define HCLGE_VF_VLAN_NO_ENTRY 2 - if (!req0->resp_code || req0->resp_code == 1) + if (!req->resp_code || req->resp_code == 1) return 0;
- if (req0->resp_code == HCLGE_VF_VLAN_NO_ENTRY) { + if (req->resp_code == HCLGE_VF_VLAN_NO_ENTRY) { set_bit(vfid, hdev->vf_vlan_full); dev_warn(&hdev->pdev->dev, "vf vlan table is full, vf vlan filter is disabled\n"); @@ -8854,10 +8848,10 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid,
dev_err(&hdev->pdev->dev, "Add vf vlan filter fail, ret =%u.\n", - req0->resp_code); + req->resp_code); } else { #define HCLGE_VF_VLAN_DEL_NO_FOUND 1 - if (!req0->resp_code) + if (!req->resp_code) return 0;
/* vf vlan filter is disabled when vf vlan table is full, @@ -8865,17 +8859,46 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid, * Just return 0 without warning, avoid massive verbose * print logs when unload. */ - if (req0->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND) + if (req->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND) return 0;
dev_err(&hdev->pdev->dev, "Kill vf vlan filter fail, ret =%u.\n", - req0->resp_code); + req->resp_code); }
return -EIO; }
+static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid, + bool is_kill, u16 vlan, + __be16 proto) +{ + struct hclge_vport *vport = &hdev->vport[vfid]; + struct hclge_desc desc[2]; + int ret; + + /* if vf vlan table is full, firmware will close vf vlan filter, it + * is unable and unnecessary to add new vlan id to vf vlan filter. + * If spoof check is enable, and vf vlan is full, it shouldn't add + * new vlan, because tx packets with these vlan id will be dropped. + */ + if (test_bit(vfid, hdev->vf_vlan_full) && !is_kill) { + if (vport->vf_info.spoofchk && vlan) { + dev_err(&hdev->pdev->dev, + "Can't add vlan due to spoof check is on and vf vlan table is full\n"); + return -EPERM; + } + return 0; + } + + ret = hclge_set_vf_vlan_filter_cmd(hdev, vfid, is_kill, vlan, desc); + if (ret) + return ret; + + return hclge_check_vf_vlan_cmd_status(hdev, vfid, is_kill, desc); +} + static int hclge_set_port_vlan_filter(struct hclge_dev *hdev, __be16 proto, u16 vlan_id, bool is_kill) {
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 405642a15cba0c01d14fc6aa9b8deadf325ab7c3 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To improve code readability and maintainability, separate the flow type parsing part and the converting part from bloated hclge_get_rss_tuple().
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 59 ++++++++++++------- 1 file changed, 38 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d7a8adc8d6d9..712616f7e4bc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4580,52 +4580,69 @@ static int hclge_set_rss_tuple(struct hnae3_handle *handle, return 0; }
-static int hclge_get_rss_tuple(struct hnae3_handle *handle, - struct ethtool_rxnfc *nfc) +static int hclge_get_vport_rss_tuple(struct hclge_vport *vport, int flow_type, + u8 *tuple_sets) { - struct hclge_vport *vport = hclge_get_vport(handle); - u8 tuple_sets; - - nfc->data = 0; - - switch (nfc->flow_type) { + switch (flow_type) { case TCP_V4_FLOW: - tuple_sets = vport->rss_tuple_sets.ipv4_tcp_en; + *tuple_sets = vport->rss_tuple_sets.ipv4_tcp_en; break; case UDP_V4_FLOW: - tuple_sets = vport->rss_tuple_sets.ipv4_udp_en; + *tuple_sets = vport->rss_tuple_sets.ipv4_udp_en; break; case TCP_V6_FLOW: - tuple_sets = vport->rss_tuple_sets.ipv6_tcp_en; + *tuple_sets = vport->rss_tuple_sets.ipv6_tcp_en; break; case UDP_V6_FLOW: - tuple_sets = vport->rss_tuple_sets.ipv6_udp_en; + *tuple_sets = vport->rss_tuple_sets.ipv6_udp_en; break; case SCTP_V4_FLOW: - tuple_sets = vport->rss_tuple_sets.ipv4_sctp_en; + *tuple_sets = vport->rss_tuple_sets.ipv4_sctp_en; break; case SCTP_V6_FLOW: - tuple_sets = vport->rss_tuple_sets.ipv6_sctp_en; + *tuple_sets = vport->rss_tuple_sets.ipv6_sctp_en; break; case IPV4_FLOW: case IPV6_FLOW: - tuple_sets = HCLGE_S_IP_BIT | HCLGE_D_IP_BIT; + *tuple_sets = HCLGE_S_IP_BIT | HCLGE_D_IP_BIT; break; default: return -EINVAL; }
- if (!tuple_sets) - return 0; + return 0; +} + +static u64 hclge_convert_rss_tuple(u8 tuple_sets) +{ + u64 tuple_data = 0;
if (tuple_sets & HCLGE_D_PORT_BIT) - nfc->data |= RXH_L4_B_2_3; + tuple_data |= RXH_L4_B_2_3; if (tuple_sets & HCLGE_S_PORT_BIT) - nfc->data |= RXH_L4_B_0_1; + tuple_data |= RXH_L4_B_0_1; if (tuple_sets & HCLGE_D_IP_BIT) - nfc->data |= RXH_IP_DST; + tuple_data |= RXH_IP_DST; if (tuple_sets & HCLGE_S_IP_BIT) - nfc->data |= RXH_IP_SRC; + tuple_data |= RXH_IP_SRC; + + return tuple_data; +} + +static int hclge_get_rss_tuple(struct hnae3_handle *handle, + struct ethtool_rxnfc *nfc) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + u8 tuple_sets; + int ret; + + nfc->data = 0; + + ret = hclge_get_vport_rss_tuple(vport, nfc->flow_type, &tuple_sets); + if (ret || !tuple_sets) + return ret; + + nfc->data = hclge_convert_rss_tuple(tuple_sets);
return 0; }
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 73f7767ed0f93cd3269e7f5af75902a351faf5da category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To improve code readability and maintainability, separate the flow type parsing part and the converting part from bloated hclgevf_get_rss_tuple().
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 67 ++++++++++++------- 1 file changed, 42 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index a345307de590..269c424e7166 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -954,56 +954,73 @@ static int hclgevf_set_rss_tuple(struct hnae3_handle *handle, return 0; }
-static int hclgevf_get_rss_tuple(struct hnae3_handle *handle, - struct ethtool_rxnfc *nfc) +static int hclgevf_get_rss_tuple_by_flow_type(struct hclgevf_dev *hdev, + int flow_type, u8 *tuple_sets) { - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; - u8 tuple_sets; - - if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) - return -EOPNOTSUPP; - - nfc->data = 0; - - switch (nfc->flow_type) { + switch (flow_type) { case TCP_V4_FLOW: - tuple_sets = rss_cfg->rss_tuple_sets.ipv4_tcp_en; + *tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv4_tcp_en; break; case UDP_V4_FLOW: - tuple_sets = rss_cfg->rss_tuple_sets.ipv4_udp_en; + *tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv4_udp_en; break; case TCP_V6_FLOW: - tuple_sets = rss_cfg->rss_tuple_sets.ipv6_tcp_en; + *tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv6_tcp_en; break; case UDP_V6_FLOW: - tuple_sets = rss_cfg->rss_tuple_sets.ipv6_udp_en; + *tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv6_udp_en; break; case SCTP_V4_FLOW: - tuple_sets = rss_cfg->rss_tuple_sets.ipv4_sctp_en; + *tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv4_sctp_en; break; case SCTP_V6_FLOW: - tuple_sets = rss_cfg->rss_tuple_sets.ipv6_sctp_en; + *tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv6_sctp_en; break; case IPV4_FLOW: case IPV6_FLOW: - tuple_sets = HCLGEVF_S_IP_BIT | HCLGEVF_D_IP_BIT; + *tuple_sets = HCLGEVF_S_IP_BIT | HCLGEVF_D_IP_BIT; break; default: return -EINVAL; }
- if (!tuple_sets) - return 0; + return 0; +} + +static u64 hclgevf_convert_rss_tuple(u8 tuple_sets) +{ + u64 tuple_data = 0;
if (tuple_sets & HCLGEVF_D_PORT_BIT) - nfc->data |= RXH_L4_B_2_3; + tuple_data |= RXH_L4_B_2_3; if (tuple_sets & HCLGEVF_S_PORT_BIT) - nfc->data |= RXH_L4_B_0_1; + tuple_data |= RXH_L4_B_0_1; if (tuple_sets & HCLGEVF_D_IP_BIT) - nfc->data |= RXH_IP_DST; + tuple_data |= RXH_IP_DST; if (tuple_sets & HCLGEVF_S_IP_BIT) - nfc->data |= RXH_IP_SRC; + tuple_data |= RXH_IP_SRC; + + return tuple_data; +} + +static int hclgevf_get_rss_tuple(struct hnae3_handle *handle, + struct ethtool_rxnfc *nfc) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + u8 tuple_sets; + int ret; + + if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) + return -EOPNOTSUPP; + + nfc->data = 0; + + ret = hclgevf_get_rss_tuple_by_flow_type(hdev, nfc->flow_type, + &tuple_sets); + if (ret || !tuple_sets) + return ret; + + nfc->data = hclgevf_convert_rss_tuple(tuple_sets);
return 0; }
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit b3712fa73d56e31e5c94375977ad25966948c6ae category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
hclge_dbg_dump_qos_buf_cfg() is bloated, so split it into separate functions for readability and maintainability.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 158 +++++++++++++----- 1 file changed, 115 insertions(+), 43 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index a0a33c02ce25..6b1d197df881 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -984,39 +984,39 @@ static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "pri_7_to_tc: 0x%x\n", pri_map->pri7_tc); }
-static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_tx_buf_cfg(struct hclge_dev *hdev) { struct hclge_tx_buff_alloc_cmd *tx_buf_cmd; - struct hclge_rx_priv_buff_cmd *rx_buf_cmd; - struct hclge_rx_priv_wl_buf *rx_priv_wl; - struct hclge_rx_com_wl *rx_packet_cnt; - struct hclge_rx_com_thrd *rx_com_thrd; - struct hclge_rx_com_wl *rx_com_wl; - enum hclge_opcode_type cmd; - struct hclge_desc desc[2]; + struct hclge_desc desc; int i, ret;
- cmd = HCLGE_OPC_TX_BUFF_ALLOC; - hclge_cmd_setup_basic_desc(desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, desc, 1); + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) - goto err_qos_cmd_send; + return ret;
dev_info(&hdev->pdev->dev, "dump qos buf cfg\n"); - - tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc[0].data; + tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc.data; for (i = 0; i < HCLGE_MAX_TC_NUM; i++) dev_info(&hdev->pdev->dev, "tx_packet_buf_tc_%d: 0x%x\n", i, le16_to_cpu(tx_buf_cmd->tx_pkt_buff[i]));
- cmd = HCLGE_OPC_RX_PRIV_BUFF_ALLOC; - hclge_cmd_setup_basic_desc(desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, desc, 1); + return 0; +} + +static int hclge_dbg_dump_rx_priv_buf_cfg(struct hclge_dev *hdev) +{ + struct hclge_rx_priv_buff_cmd *rx_buf_cmd; + struct hclge_desc desc; + int i, ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_PRIV_BUFF_ALLOC, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) - goto err_qos_cmd_send; + return ret;
dev_info(&hdev->pdev->dev, "\n"); - rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc[0].data; + rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc.data; for (i = 0; i < HCLGE_MAX_TC_NUM; i++) dev_info(&hdev->pdev->dev, "rx_packet_buf_tc_%d: 0x%x\n", i, le16_to_cpu(rx_buf_cmd->buf_num[i])); @@ -1024,43 +1024,61 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "rx_share_buf: 0x%x\n", le16_to_cpu(rx_buf_cmd->shared_buf));
- cmd = HCLGE_OPC_RX_COM_WL_ALLOC; - hclge_cmd_setup_basic_desc(desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, desc, 1); + return 0; +} + +static int hclge_dbg_dump_rx_common_wl_cfg(struct hclge_dev *hdev) +{ + struct hclge_rx_com_wl *rx_com_wl; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_COM_WL_ALLOC, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) - goto err_qos_cmd_send; + return ret;
- rx_com_wl = (struct hclge_rx_com_wl *)desc[0].data; + rx_com_wl = (struct hclge_rx_com_wl *)desc.data; dev_info(&hdev->pdev->dev, "\n"); dev_info(&hdev->pdev->dev, "rx_com_wl: high: 0x%x, low: 0x%x\n", le16_to_cpu(rx_com_wl->com_wl.high), le16_to_cpu(rx_com_wl->com_wl.low));
- cmd = HCLGE_OPC_RX_GBL_PKT_CNT; - hclge_cmd_setup_basic_desc(desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, desc, 1); + return 0; +} + +static int hclge_dbg_dump_rx_global_pkt_cnt(struct hclge_dev *hdev) +{ + struct hclge_rx_com_wl *rx_packet_cnt; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_GBL_PKT_CNT, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) - goto err_qos_cmd_send; + return ret;
- rx_packet_cnt = (struct hclge_rx_com_wl *)desc[0].data; + rx_packet_cnt = (struct hclge_rx_com_wl *)desc.data; dev_info(&hdev->pdev->dev, "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n", le16_to_cpu(rx_packet_cnt->com_wl.high), le16_to_cpu(rx_packet_cnt->com_wl.low)); - dev_info(&hdev->pdev->dev, "\n");
- if (!hnae3_dev_dcb_supported(hdev)) { - dev_info(&hdev->pdev->dev, - "Only DCB-supported dev supports rx priv wl\n"); - return; - } - cmd = HCLGE_OPC_RX_PRIV_WL_ALLOC; - hclge_cmd_setup_basic_desc(&desc[0], cmd, true); + return 0; +} + +static int hclge_dbg_dump_rx_priv_wl_buf_cfg(struct hclge_dev *hdev) +{ + struct hclge_rx_priv_wl_buf *rx_priv_wl; + struct hclge_desc desc[2]; + int i, ret; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_RX_PRIV_WL_ALLOC, true); desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); - hclge_cmd_setup_basic_desc(&desc[1], cmd, true); + hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_RX_PRIV_WL_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, desc, 2); if (ret) - goto err_qos_cmd_send; + return ret;
rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[0].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) @@ -1077,13 +1095,21 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) le16_to_cpu(rx_priv_wl->tc_wl[i].high), le16_to_cpu(rx_priv_wl->tc_wl[i].low));
- cmd = HCLGE_OPC_RX_COM_THRD_ALLOC; - hclge_cmd_setup_basic_desc(&desc[0], cmd, true); + return 0; +} + +static int hclge_dbg_dump_rx_common_threshold_cfg(struct hclge_dev *hdev) +{ + struct hclge_rx_com_thrd *rx_com_thrd; + struct hclge_desc desc[2]; + int i, ret; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_RX_COM_THRD_ALLOC, true); desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); - hclge_cmd_setup_basic_desc(&desc[1], cmd, true); + hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_RX_COM_THRD_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, desc, 2); if (ret) - goto err_qos_cmd_send; + return ret;
dev_info(&hdev->pdev->dev, "\n"); rx_com_thrd = (struct hclge_rx_com_thrd *)desc[0].data; @@ -1100,6 +1126,52 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) i + HCLGE_TC_NUM_ONE_DESC, le16_to_cpu(rx_com_thrd->com_thrd[i].high), le16_to_cpu(rx_com_thrd->com_thrd[i].low)); + + return 0; +} + +static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) +{ + enum hclge_opcode_type cmd; + int ret; + + cmd = HCLGE_OPC_TX_BUFF_ALLOC; + ret = hclge_dbg_dump_tx_buf_cfg(hdev); + if (ret) + goto err_qos_cmd_send; + + cmd = HCLGE_OPC_RX_PRIV_BUFF_ALLOC; + ret = hclge_dbg_dump_rx_priv_buf_cfg(hdev); + if (ret) + goto err_qos_cmd_send; + + cmd = HCLGE_OPC_RX_COM_WL_ALLOC; + ret = hclge_dbg_dump_rx_common_wl_cfg(hdev); + if (ret) + goto err_qos_cmd_send; + + cmd = HCLGE_OPC_RX_GBL_PKT_CNT; + ret = hclge_dbg_dump_rx_global_pkt_cnt(hdev); + if (ret) + goto err_qos_cmd_send; + + dev_info(&hdev->pdev->dev, "\n"); + if (!hnae3_dev_dcb_supported(hdev)) { + dev_info(&hdev->pdev->dev, + "Only DCB-supported dev supports rx priv wl\n"); + return; + } + + cmd = HCLGE_OPC_RX_PRIV_WL_ALLOC; + ret = hclge_dbg_dump_rx_priv_wl_buf_cfg(hdev); + if (ret) + goto err_qos_cmd_send; + + cmd = HCLGE_OPC_RX_COM_THRD_ALLOC; + ret = hclge_dbg_dump_rx_common_threshold_cfg(hdev); + if (ret) + goto err_qos_cmd_send; + return;
err_qos_cmd_send:
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 76f82fd9b1230332db2b3bc3916d097b92acbf29 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
hclge_cmd_send() is bloated, so split it into separate functions for readability and maintainability.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 100 +++++++++++------- 1 file changed, 59 insertions(+), 41 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index cb2c955ce52c..1bd0ddfaec4d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -194,6 +194,22 @@ struct errcode { int common_errno; };
+static void hclge_cmd_copy_desc(struct hclge_hw *hw, struct hclge_desc *desc, + int num) +{ + struct hclge_desc *desc_to_use; + int handle = 0; + + while (handle < num) { + desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use]; + *desc_to_use = desc[handle]; + (hw->cmq.csq.next_to_use)++; + if (hw->cmq.csq.next_to_use >= hw->cmq.csq.desc_num) + hw->cmq.csq.next_to_use = 0; + handle++; + } +} + static int hclge_cmd_convert_err_code(u16 desc_ret) { struct errcode hclge_cmd_errcode[] = { @@ -243,6 +259,44 @@ static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc, return hclge_cmd_convert_err_code(desc_ret); }
+static int hclge_cmd_check_result(struct hclge_hw *hw, struct hclge_desc *desc, + int num, int ntc) +{ + struct hclge_dev *hdev = container_of(hw, struct hclge_dev, hw); + bool is_completed = false; + u32 timeout = 0; + int handle, ret; + + /** + * If the command is sync, wait for the firmware to write back, + * if multi descriptors to be sent, use the first one to check + */ + if (HCLGE_SEND_SYNC(le16_to_cpu(desc->flag))) { + do { + if (hclge_cmd_csq_done(hw)) { + is_completed = true; + break; + } + udelay(1); + timeout++; + } while (timeout < hw->cmq.tx_timeout); + } + + if (!is_completed) + ret = -EBADE; + else + ret = hclge_cmd_check_retval(hw, desc, num, ntc); + + /* Clean the command send queue */ + handle = hclge_cmd_csq_clean(hw); + if (handle < 0) + ret = handle; + else if (handle != num) + dev_warn(&hdev->pdev->dev, + "cleaned %d, need to clean %d\n", handle, num); + return ret; +} + /** * hclge_cmd_send - send command to command queue * @hw: pointer to the hw struct @@ -256,11 +310,7 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) { struct hclge_dev *hdev = container_of(hw, struct hclge_dev, hw); struct hclge_cmq_ring *csq = &hw->cmq.csq; - struct hclge_desc *desc_to_use; - bool complete = false; - u32 timeout = 0; - int handle = 0; - int retval; + int ret; int ntc;
spin_lock_bh(&hw->cmq.csq.lock); @@ -284,49 +334,17 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) * which will be use for hardware to write back */ ntc = hw->cmq.csq.next_to_use; - while (handle < num) { - desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use]; - *desc_to_use = desc[handle]; - (hw->cmq.csq.next_to_use)++; - if (hw->cmq.csq.next_to_use >= hw->cmq.csq.desc_num) - hw->cmq.csq.next_to_use = 0; - handle++; - } + + hclge_cmd_copy_desc(hw, desc, num);
/* Write to hardware */ hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, hw->cmq.csq.next_to_use);
- /** - * If the command is sync, wait for the firmware to write back, - * if multi descriptors to be sent, use the first one to check - */ - if (HCLGE_SEND_SYNC(le16_to_cpu(desc->flag))) { - do { - if (hclge_cmd_csq_done(hw)) { - complete = true; - break; - } - udelay(1); - timeout++; - } while (timeout < hw->cmq.tx_timeout); - } - - if (!complete) - retval = -EBADE; - else - retval = hclge_cmd_check_retval(hw, desc, num, ntc); - - /* Clean the command send queue */ - handle = hclge_cmd_csq_clean(hw); - if (handle < 0) - retval = handle; - else if (handle != num) - dev_warn(&hdev->pdev->dev, - "cleaned %d, need to clean %d\n", handle, num); + ret = hclge_cmd_check_result(hw, desc, num, ntc);
spin_unlock_bh(&hw->cmq.csq.lock);
- return retval; + return ret; }
static void hclge_set_default_capability(struct hclge_dev *hdev)
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit eb0faf32b86e208049b6432197bfeeeac8580fe1 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
hclgevf_cmd_send() is bloated, so split it into separate functions for readability and maintainability.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3vf/hclgevf_cmd.c | 141 ++++++++++-------- 1 file changed, 81 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 603665e5bf39..46700c427849 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -181,6 +181,22 @@ struct vf_errcode { int common_errno; };
+static void hclgevf_cmd_copy_desc(struct hclgevf_hw *hw, + struct hclgevf_desc *desc, int num) +{ + struct hclgevf_desc *desc_to_use; + int handle = 0; + + while (handle < num) { + desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use]; + *desc_to_use = desc[handle]; + (hw->cmq.csq.next_to_use)++; + if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num) + hw->cmq.csq.next_to_use = 0; + handle++; + } +} + static int hclgevf_cmd_convert_err_code(u16 desc_ret) { struct vf_errcode hclgevf_cmd_errcode[] = { @@ -207,6 +223,66 @@ static int hclgevf_cmd_convert_err_code(u16 desc_ret) return -EIO; }
+static int hclgevf_cmd_check_retval(struct hclgevf_hw *hw, + struct hclgevf_desc *desc, int num, int ntc) +{ + u16 opcode, desc_ret; + int handle; + + opcode = le16_to_cpu(desc[0].opcode); + for (handle = 0; handle < num; handle++) { + /* Get the result of hardware write back */ + desc[handle] = hw->cmq.csq.desc[ntc]; + ntc++; + if (ntc == hw->cmq.csq.desc_num) + ntc = 0; + } + if (likely(!hclgevf_is_special_opcode(opcode))) + desc_ret = le16_to_cpu(desc[num - 1].retval); + else + desc_ret = le16_to_cpu(desc[0].retval); + hw->cmq.last_status = desc_ret; + + return hclgevf_cmd_convert_err_code(desc_ret); +} + +static int hclgevf_cmd_check_result(struct hclgevf_hw *hw, + struct hclgevf_desc *desc, int num, int ntc) +{ + struct hclgevf_dev *hdev = (struct hclgevf_dev *)hw->hdev; + bool is_completed = false; + u32 timeout = 0; + int handle, ret; + + /* If the command is sync, wait for the firmware to write back, + * if multi descriptors to be sent, use the first one to check + */ + if (HCLGEVF_SEND_SYNC(le16_to_cpu(desc->flag))) { + do { + if (hclgevf_cmd_csq_done(hw)) { + is_completed = true; + break; + } + udelay(1); + timeout++; + } while (timeout < hw->cmq.tx_timeout); + } + + if (!is_completed) + ret = -EBADE; + else + ret = hclgevf_cmd_check_retval(hw, desc, num, ntc); + + /* Clean the command send queue */ + handle = hclgevf_cmd_csq_clean(hw); + if (handle < 0) + ret = handle; + else if (handle != num) + dev_warn(&hdev->pdev->dev, + "cleaned %d, need to clean %d\n", handle, num); + return ret; +} + /* hclgevf_cmd_send - send command to command queue * @hw: pointer to the hw struct * @desc: prefilled descriptor for describing the command @@ -219,13 +295,7 @@ int hclgevf_cmd_send(struct hclgevf_hw *hw, struct hclgevf_desc *desc, int num) { struct hclgevf_dev *hdev = (struct hclgevf_dev *)hw->hdev; struct hclgevf_cmq_ring *csq = &hw->cmq.csq; - struct hclgevf_desc *desc_to_use; - bool complete = false; - u32 timeout = 0; - int handle = 0; - int status = 0; - u16 retval; - u16 opcode; + int ret; int ntc;
spin_lock_bh(&hw->cmq.csq.lock); @@ -249,67 +319,18 @@ int hclgevf_cmd_send(struct hclgevf_hw *hw, struct hclgevf_desc *desc, int num) * which will be use for hardware to write back */ ntc = hw->cmq.csq.next_to_use; - opcode = le16_to_cpu(desc[0].opcode); - while (handle < num) { - desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use]; - *desc_to_use = desc[handle]; - (hw->cmq.csq.next_to_use)++; - if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num) - hw->cmq.csq.next_to_use = 0; - handle++; - } + + hclgevf_cmd_copy_desc(hw, desc, num);
/* Write to hardware */ hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG, hw->cmq.csq.next_to_use);
- /* If the command is sync, wait for the firmware to write back, - * if multi descriptors to be sent, use the first one to check - */ - if (HCLGEVF_SEND_SYNC(le16_to_cpu(desc->flag))) { - do { - if (hclgevf_cmd_csq_done(hw)) - break; - udelay(1); - timeout++; - } while (timeout < hw->cmq.tx_timeout); - } - - if (hclgevf_cmd_csq_done(hw)) { - complete = true; - handle = 0; - - while (handle < num) { - /* Get the result of hardware write back */ - desc_to_use = &hw->cmq.csq.desc[ntc]; - desc[handle] = *desc_to_use; - - if (likely(!hclgevf_is_special_opcode(opcode))) - retval = le16_to_cpu(desc[handle].retval); - else - retval = le16_to_cpu(desc[0].retval); - - status = hclgevf_cmd_convert_err_code(retval); - hw->cmq.last_status = (enum hclgevf_cmd_status)retval; - ntc++; - handle++; - if (ntc == hw->cmq.csq.desc_num) - ntc = 0; - } - } - - if (!complete) - status = -EBADE; - - /* Clean the command send queue */ - handle = hclgevf_cmd_csq_clean(hw); - if (handle != num) - dev_warn(&hdev->pdev->dev, - "cleaned %d, need to clean %d\n", handle, num); + ret = hclgevf_cmd_check_result(hw, desc, num, ntc);
spin_unlock_bh(&hw->cmq.csq.lock);
- return status; + return ret; }
static void hclgevf_set_default_capability(struct hclgevf_dev *hdev)
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit e291eff3bce4efc4d81fa71e5c57f50283f63f2c category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To make it more readable and maintainable, split hclge_set_rss_tuple() into two parts.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 712616f7e4bc..43f35cb213b8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4501,22 +4501,12 @@ static u8 hclge_get_rss_hash_bits(struct ethtool_rxnfc *nfc) return hash_sets; }
-static int hclge_set_rss_tuple(struct hnae3_handle *handle, - struct ethtool_rxnfc *nfc) +static int hclge_init_rss_tuple_cmd(struct hclge_vport *vport, + struct ethtool_rxnfc *nfc, + struct hclge_rss_input_tuple_cmd *req) { - struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - struct hclge_rss_input_tuple_cmd *req; - struct hclge_desc desc; u8 tuple_sets; - int ret; - - if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | - RXH_L4_B_0_1 | RXH_L4_B_2_3)) - return -EINVAL; - - req = (struct hclge_rss_input_tuple_cmd *)desc.data; - hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, false);
req->ipv4_tcp_en = vport->rss_tuple_sets.ipv4_tcp_en; req->ipv4_udp_en = vport->rss_tuple_sets.ipv4_udp_en; @@ -4561,6 +4551,32 @@ static int hclge_set_rss_tuple(struct hnae3_handle *handle, return -EINVAL; }
+ return 0; +} + +static int hclge_set_rss_tuple(struct hnae3_handle *handle, + struct ethtool_rxnfc *nfc) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + struct hclge_rss_input_tuple_cmd *req; + struct hclge_desc desc; + int ret; + + if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + req = (struct hclge_rss_input_tuple_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, false); + + ret = hclge_init_rss_tuple_cmd(vport, nfc, req); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to init rss tuple cmd, ret = %d\n", ret); + return ret; + } + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev,
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 5fd0e7b4f7bf2c3d22ee8c973b215de9010eb45c category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To make it more readable and maintainable, split hclgevf_set_rss_tuple() into two parts.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 269c424e7166..14b83eca0a5e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -873,25 +873,13 @@ static u8 hclgevf_get_rss_hash_bits(struct ethtool_rxnfc *nfc) return hash_sets; }
-static int hclgevf_set_rss_tuple(struct hnae3_handle *handle, - struct ethtool_rxnfc *nfc) +static int hclgevf_init_rss_tuple_cmd(struct hnae3_handle *handle, + struct ethtool_rxnfc *nfc, + struct hclgevf_rss_input_tuple_cmd *req) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; - struct hclgevf_rss_input_tuple_cmd *req; - struct hclgevf_desc desc; u8 tuple_sets; - int ret; - - if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) - return -EOPNOTSUPP; - - if (nfc->data & - ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) - return -EINVAL; - - req = (struct hclgevf_rss_input_tuple_cmd *)desc.data; - hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en; req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en; @@ -936,6 +924,35 @@ static int hclgevf_set_rss_tuple(struct hnae3_handle *handle, return -EINVAL; }
+ return 0; +} + +static int hclgevf_set_rss_tuple(struct hnae3_handle *handle, + struct ethtool_rxnfc *nfc) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; + struct hclgevf_rss_input_tuple_cmd *req; + struct hclgevf_desc desc; + int ret; + + if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) + return -EOPNOTSUPP; + + if (nfc->data & + ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + req = (struct hclgevf_rss_input_tuple_cmd *)desc.data; + hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false); + + ret = hclgevf_init_rss_tuple_cmd(handle, nfc, req); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to init rss tuple cmd, ret = %d\n", ret); + return ret; + } + ret = hclgevf_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev,
From: Hao Chen chenhao288@hisilicon.com
mainline inclusion from mainline-v5.12-rc1-dontuse commit 80a9f3f1fa81c75b45c9073b46372ec7ee55fedf category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
hclge_rm_vport_all_mac_table() is bloated, so split it into separate functions for readability and maintainability.
Signed-off-by: Hao Chen chenhao288@hisilicon.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 43f35cb213b8..19c7b612aa51 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8352,36 +8352,18 @@ static void hclge_sync_mac_table(struct hclge_dev *hdev) } }
-void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, - enum HCLGE_MAC_ADDR_TYPE mac_type) +static void hclge_build_del_list(struct list_head *list, + bool is_del_list, + struct list_head *tmp_del_list) { - int (*unsync)(struct hclge_vport *vport, const unsigned char *addr); struct hclge_mac_node *mac_cfg, *tmp; - struct hclge_dev *hdev = vport->back; - struct list_head tmp_del_list, *list; - int ret; - - if (mac_type == HCLGE_MAC_ADDR_UC) { - list = &vport->uc_mac_list; - unsync = hclge_rm_uc_addr_common; - } else { - list = &vport->mc_mac_list; - unsync = hclge_rm_mc_addr_common; - } - - INIT_LIST_HEAD(&tmp_del_list); - - if (!is_del_list) - set_bit(vport->vport_id, hdev->vport_config_block); - - spin_lock_bh(&vport->mac_list_lock);
list_for_each_entry_safe(mac_cfg, tmp, list, node) { switch (mac_cfg->state) { case HCLGE_MAC_TO_DEL: case HCLGE_MAC_ACTIVE: list_del(&mac_cfg->node); - list_add_tail(&mac_cfg->node, &tmp_del_list); + list_add_tail(&mac_cfg->node, tmp_del_list); break; case HCLGE_MAC_TO_ADD: if (is_del_list) { @@ -8391,10 +8373,18 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, break; } } +}
- spin_unlock_bh(&vport->mac_list_lock); +static void hclge_unsync_del_list(struct hclge_vport *vport, + int (*unsync)(struct hclge_vport *vport, + const unsigned char *addr), + bool is_del_list, + struct list_head *tmp_del_list) +{ + struct hclge_mac_node *mac_cfg, *tmp; + int ret;
- list_for_each_entry_safe(mac_cfg, tmp, &tmp_del_list, node) { + list_for_each_entry_safe(mac_cfg, tmp, tmp_del_list, node) { ret = unsync(vport, mac_cfg->mac_addr); if (!ret || ret == -ENOENT) { /* clear all mac addr from hardware, but remain these @@ -8412,6 +8402,35 @@ void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, mac_cfg->state = HCLGE_MAC_TO_DEL; } } +} + +void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, + enum HCLGE_MAC_ADDR_TYPE mac_type) +{ + int (*unsync)(struct hclge_vport *vport, const unsigned char *addr); + struct hclge_dev *hdev = vport->back; + struct list_head tmp_del_list, *list; + + if (mac_type == HCLGE_MAC_ADDR_UC) { + list = &vport->uc_mac_list; + unsync = hclge_rm_uc_addr_common; + } else { + list = &vport->mc_mac_list; + unsync = hclge_rm_mc_addr_common; + } + + INIT_LIST_HEAD(&tmp_del_list); + + if (!is_del_list) + set_bit(vport->vport_id, hdev->vport_config_block); + + spin_lock_bh(&vport->mac_list_lock); + + hclge_build_del_list(list, is_del_list, &tmp_del_list); + + spin_unlock_bh(&vport->mac_list_lock); + + hclge_unsync_del_list(vport, unsync, is_del_list, &tmp_del_list);
spin_lock_bh(&vport->mac_list_lock);
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 433ccce83504a44d8e07ac2c5282ed24095af602 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
For maintainability and compatibility, add support to use FEC capability queried from firmware.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 6 +++++- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 ++++++---- 3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 1bd0ddfaec4d..02419bb461e1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -353,7 +353,9 @@ static void hclge_set_default_capability(struct hclge_dev *hdev)
set_bit(HNAE3_DEV_SUPPORT_FD_B, ae_dev->caps); set_bit(HNAE3_DEV_SUPPORT_GRO_B, ae_dev->caps); - set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); + if (hdev->ae_dev->dev_version == HNAE3_DEVICE_VERSION_V2) { + set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); + } }
static void hclge_parse_capability(struct hclge_dev *hdev, @@ -378,6 +380,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_FD_FORWARD_TC_B)) set_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGE_CAP_FEC_B)) + set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); }
static __le32 hclge_build_api_caps(void) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 057dda735492..e8480ff680f4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -384,6 +384,7 @@ enum HCLGE_CAP_BITS { HCLGE_CAP_HW_PAD_B, HCLGE_CAP_STASH_B, HCLGE_CAP_UDP_TUNNEL_CSUM_B, + HCLGE_CAP_FEC_B = 13, };
enum HCLGE_API_CAP_BITS { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 19c7b612aa51..c74bc110632b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2889,10 +2889,12 @@ static void hclge_update_link_status(struct hclge_dev *hdev) clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); }
-static void hclge_update_port_capability(struct hclge_mac *mac) +static void hclge_update_port_capability(struct hclge_dev *hdev, + struct hclge_mac *mac) { - /* update fec ability by speed */ - hclge_convert_setting_fec(mac); + if (hnae3_dev_fec_supported(hdev)) + /* update fec ability by speed */ + hclge_convert_setting_fec(mac);
/* firmware can not identify back plane type, the media type * read from configuration can help deal it @@ -3012,7 +3014,7 @@ static int hclge_update_port_info(struct hclge_dev *hdev)
if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { if (mac->speed_type == QUERY_ACTIVE_SPEED) { - hclge_update_port_capability(mac); + hclge_update_port_capability(hdev, mac); return 0; } return hclge_cfg_mac_speed_dup(hdev, mac->speed,
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit e8194f3262055bc2e6e2b7c02f9de2c3d2ef7fc9 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
For maintainability and compatibility, add support to use pause capability queried from firmware, and add debugfs support to dump this capability.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 ++++ .../net/ethernet/hisilicon/hns3/hns3_debugfs.c | 3 +++ .../net/ethernet/hisilicon/hns3/hns3_ethtool.c | 8 ++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 3 +++ .../ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 16 ++++++++++++---- 6 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 406393990c7d..18105e70e0c4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -89,6 +89,7 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_HW_PAD_B, HNAE3_DEV_SUPPORT_STASH_B, HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, + HNAE3_DEV_SUPPORT_PAUSE_B, };
#define hnae3_dev_fd_supported(hdev) \ @@ -133,6 +134,9 @@ enum HNAE3_DEV_CAP_BITS { #define hnae3_dev_stash_supported(hdev) \ test_bit(HNAE3_DEV_SUPPORT_STASH_B, (hdev)->ae_dev->caps)
+#define hnae3_dev_pause_supported(hdev) \ + test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, (hdev)->ae_dev->caps) + #define hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev) \ test_bit(HNAE3_DEV_SUPPORT_TQP_TXRX_INDEP_B, (ae_dev)->caps)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index dd11c57027bb..ded92ea50971 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -362,6 +362,9 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h) dev_info(&h->pdev->dev, "support UDP tunnel csum: %s\n", test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, caps) ? "yes" : "no"); + dev_info(&h->pdev->dev, "support PAUSE: %s\n", + test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps) ? + "yes" : "no"); }
static void hns3_dbg_dev_specs(struct hnae3_handle *h) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index d20f2e246017..74ec835a9255 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -644,6 +644,10 @@ static void hns3_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *param) { struct hnae3_handle *h = hns3_get_handle(netdev); + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); + + if (!test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps)) + return;
if (h->ae_algo->ops->get_pauseparam) h->ae_algo->ops->get_pauseparam(h, ¶m->autoneg, @@ -654,6 +658,10 @@ static int hns3_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *param) { struct hnae3_handle *h = hns3_get_handle(netdev); + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); + + if (!test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps)) + return -EOPNOTSUPP;
netif_dbg(h, drv, netdev, "set pauseparam: autoneg=%u, rx:%u, tx:%u\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 02419bb461e1..1c90c6b8a9a3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -355,6 +355,7 @@ static void hclge_set_default_capability(struct hclge_dev *hdev) set_bit(HNAE3_DEV_SUPPORT_GRO_B, ae_dev->caps); if (hdev->ae_dev->dev_version == HNAE3_DEVICE_VERSION_V2) { set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); + set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps); } }
@@ -382,6 +383,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_FD_FORWARD_TC_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_FEC_B)) set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGE_CAP_PAUSE_B)) + set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps); }
static __le32 hclge_build_api_caps(void) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index e8480ff680f4..774a9ad32752 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -385,6 +385,7 @@ enum HCLGE_CAP_BITS { HCLGE_CAP_STASH_B, HCLGE_CAP_UDP_TUNNEL_CSUM_B, HCLGE_CAP_FEC_B = 13, + HCLGE_CAP_PAUSE_B = 14, };
enum HCLGE_API_CAP_BITS { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c74bc110632b..19df8835a3ac 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1150,8 +1150,10 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev, if (hnae3_dev_fec_supported(hdev)) hclge_convert_setting_fec(mac);
+ if (hnae3_dev_pause_supported(hdev)) + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mac->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, mac->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mac->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, mac->supported); }
@@ -1163,8 +1165,11 @@ static void hclge_parse_backplane_link_mode(struct hclge_dev *hdev, hclge_convert_setting_kr(mac, speed_ability); if (hnae3_dev_fec_supported(hdev)) hclge_convert_setting_fec(mac); + + if (hnae3_dev_pause_supported(hdev)) + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mac->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, mac->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mac->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, mac->supported); }
@@ -1193,10 +1198,13 @@ static void hclge_parse_copper_link_mode(struct hclge_dev *hdev, linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported); }
+ if (hnae3_dev_pause_supported(hdev)) { + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported); + } + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported); linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported); }
static void hclge_parse_link_mode(struct hclge_dev *hdev, u16 speed_ability)
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit f5f2b3e4dcc0e944dc33b522df84576679fbd8eb category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
IMP(Intelligent Management Processor) firmware add a new feature to take control of PHYs for some new devices, PF driver adds support for this feature.
Driver queries device's capability to check whether IMP supports this feature, it will tell IMP to enable this feature by firmware compatible command if it is supported.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 2 + .../ethernet/hisilicon/hns3/hns3_ethtool.c | 9 +- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 4 + .../hisilicon/hns3/hns3pf/hclge_cmd.h | 27 ++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 149 +++++++++++++++++- 6 files changed, 192 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 18105e70e0c4..227b200cc6c5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -652,6 +652,10 @@ struct hnae3_ae_ops { int (*del_cls_flower)(struct hnae3_handle *handle, struct flow_cls_offload *cls_flower); bool (*cls_flower_active)(struct hnae3_handle *handle); + int (*get_phy_link_ksettings)(struct hnae3_handle *handle, + struct ethtool_link_ksettings *cmd); + int (*set_phy_link_ksettings)(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd); };
struct hnae3_dcb_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index ded92ea50971..9d702bd0c7c1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -365,6 +365,8 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h) dev_info(&h->pdev->dev, "support PAUSE: %s\n", test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps) ? "yes" : "no"); + dev_info(&h->pdev->dev, "support imp-controlled PHY: %s\n", + test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, caps) ? "yes" : "no"); }
static void hns3_dbg_dev_specs(struct hnae3_handle *h) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 74ec835a9255..74a97daf7080 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -702,6 +702,7 @@ static int hns3_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) { struct hnae3_handle *h = hns3_get_handle(netdev); + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); const struct hnae3_ae_ops *ops; u8 module_type; u8 media_type; @@ -732,7 +733,10 @@ static int hns3_get_link_ksettings(struct net_device *netdev, break; case HNAE3_MEDIA_TYPE_COPPER: cmd->base.port = PORT_TP; - if (!netdev->phydev) + if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && + ops->get_phy_link_ksettings) + ops->get_phy_link_ksettings(h, cmd); + else if (!netdev->phydev) hns3_get_ksettings(h, cmd); else phy_ethtool_ksettings_get(netdev->phydev, cmd); @@ -825,6 +829,9 @@ static int hns3_set_link_ksettings(struct net_device *netdev, return -EINVAL;
return phy_ethtool_ksettings_set(netdev->phydev, cmd); + } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && + ops->set_phy_link_ksettings) { + return ops->set_phy_link_ksettings(handle, cmd); }
if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 1c90c6b8a9a3..3284a2cb52e6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -385,6 +385,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_PAUSE_B)) set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGE_CAP_PHY_IMP_B)) + set_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps); }
static __le32 hclge_build_api_caps(void) @@ -474,6 +476,8 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev)
hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1); hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1); + if (hnae3_dev_phy_imp_supported(hdev)) + hnae3_set_bit(compat, HCLGE_PHY_IMP_EN_B, 1); req->compat = cpu_to_le32(compat);
return hclge_cmd_send(&hdev->hw, &desc, 1); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 774a9ad32752..f45ceaa8126f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -303,6 +303,9 @@ enum hclge_opcode_type { HCLGE_PPP_CMD1_INT_CMD = 0x2101, HCLGE_MAC_ETHERTYPE_IDX_RD = 0x2105, HCLGE_NCSI_INT_EN = 0x2401, + + /* PHY command */ + HCLGE_OPC_PHY_LINK_KSETTING = 0x7025, };
#define HCLGE_TQP_REG_OFFSET 0x80000 @@ -1098,6 +1101,7 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd {
#define HCLGE_LINK_EVENT_REPORT_EN_B 0 #define HCLGE_NCSI_ERROR_REPORT_EN_B 1 +#define HCLGE_PHY_IMP_EN_B 2 struct hclge_firmware_compat_cmd { __le32 compat; u8 rsv[20]; @@ -1139,6 +1143,29 @@ struct hclge_dev_specs_1_cmd { u8 rsv1[18]; };
+#define HCLGE_PHY_LINK_SETTING_BD_NUM 2 + +struct hclge_phy_link_ksetting_0_cmd { + __le32 speed; + u8 duplex; + u8 autoneg; + u8 eth_tp_mdix; + u8 eth_tp_mdix_ctrl; + u8 port; + u8 transceiver; + u8 phy_address; + u8 rsv; + __le32 supported; + __le32 advertising; + __le32 lp_advertising; +}; + +struct hclge_phy_link_ksetting_1_cmd { + u8 master_slave_cfg; + u8 master_slave_state; + u8 rsv[22]; +}; + int hclge_cmd_init(struct hclge_dev *hdev); static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 19df8835a3ac..3905fa933bc9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2994,6 +2994,141 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac) return 0; }
+static int hclge_get_phy_link_ksettings(struct hnae3_handle *handle, + struct ethtool_link_ksettings *cmd) +{ + struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM]; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_phy_link_ksetting_0_cmd *req0; + struct hclge_phy_link_ksetting_1_cmd *req1; + u32 supported, advertising, lp_advertising; + struct hclge_dev *hdev = vport->back; + int ret; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING, + true); + desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); + hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_PHY_LINK_KSETTING, + true); + + ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get phy link ksetting, ret = %d.\n", ret); + return ret; + } + + req0 = (struct hclge_phy_link_ksetting_0_cmd *)desc[0].data; + cmd->base.autoneg = req0->autoneg; + cmd->base.speed = le32_to_cpu(req0->speed); + cmd->base.duplex = req0->duplex; + cmd->base.port = req0->port; + cmd->base.transceiver = req0->transceiver; + cmd->base.phy_address = req0->phy_address; + cmd->base.eth_tp_mdix = req0->eth_tp_mdix; + cmd->base.eth_tp_mdix_ctrl = req0->eth_tp_mdix_ctrl; + supported = le32_to_cpu(req0->supported); + advertising = le32_to_cpu(req0->advertising); + lp_advertising = le32_to_cpu(req0->lp_advertising); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, + lp_advertising); + + req1 = (struct hclge_phy_link_ksetting_1_cmd *)desc[1].data; + cmd->base.master_slave_cfg = req1->master_slave_cfg; + cmd->base.master_slave_state = req1->master_slave_state; + + return 0; +} + +static int +hclge_set_phy_link_ksettings(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) +{ + struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM]; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_phy_link_ksetting_0_cmd *req0; + struct hclge_phy_link_ksetting_1_cmd *req1; + struct hclge_dev *hdev = vport->back; + u32 advertising; + int ret; + + if (cmd->base.autoneg == AUTONEG_DISABLE && + ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) || + (cmd->base.duplex != DUPLEX_HALF && + cmd->base.duplex != DUPLEX_FULL))) + return -EINVAL; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING, + false); + desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); + hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_PHY_LINK_KSETTING, + false); + + req0 = (struct hclge_phy_link_ksetting_0_cmd *)desc[0].data; + req0->autoneg = cmd->base.autoneg; + req0->speed = cpu_to_le32(cmd->base.speed); + req0->duplex = cmd->base.duplex; + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + req0->advertising = cpu_to_le32(advertising); + req0->eth_tp_mdix_ctrl = cmd->base.eth_tp_mdix_ctrl; + + req1 = (struct hclge_phy_link_ksetting_1_cmd *)desc[1].data; + req1->master_slave_cfg = cmd->base.master_slave_cfg; + + ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to set phy link ksettings, ret = %d.\n", ret); + return ret; + } + + hdev->hw.mac.autoneg = cmd->base.autoneg; + hdev->hw.mac.speed = cmd->base.speed; + hdev->hw.mac.duplex = cmd->base.duplex; + linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); + + return 0; +} + +static int hclge_update_tp_port_info(struct hclge_dev *hdev) +{ + struct ethtool_link_ksettings cmd; + int ret; + + if (!hnae3_dev_phy_imp_supported(hdev)) + return 0; + + ret = hclge_get_phy_link_ksettings(&hdev->vport->nic, &cmd); + if (ret) + return ret; + + hdev->hw.mac.autoneg = cmd.base.autoneg; + hdev->hw.mac.speed = cmd.base.speed; + hdev->hw.mac.duplex = cmd.base.duplex; + + return 0; +} + +static int hclge_tp_port_init(struct hclge_dev *hdev) +{ + struct ethtool_link_ksettings cmd; + + if (!hnae3_dev_phy_imp_supported(hdev)) + return 0; + + cmd.base.autoneg = hdev->hw.mac.autoneg; + cmd.base.speed = hdev->hw.mac.speed; + cmd.base.duplex = hdev->hw.mac.duplex; + linkmode_copy(cmd.link_modes.advertising, hdev->hw.mac.advertising); + + return hclge_set_phy_link_ksettings(&hdev->vport->nic, &cmd); +} + static int hclge_update_port_info(struct hclge_dev *hdev) { struct hclge_mac *mac = &hdev->hw.mac; @@ -3002,7 +3137,7 @@ static int hclge_update_port_info(struct hclge_dev *hdev)
/* get the port info from SFP cmd if not copper port */ if (mac->media_type == HNAE3_MEDIA_TYPE_COPPER) - return 0; + return hclge_update_tp_port_info(hdev);
/* if IMP does not support get SFP/qSFP info, return directly */ if (!hdev->support_sfp_query) @@ -10648,7 +10783,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) if (ret) goto err_msi_irq_uninit;
- if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) { + if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER && + !hnae3_dev_phy_imp_supported(hdev)) { ret = hclge_mac_mdio_config(hdev); if (ret) goto err_msi_irq_uninit; @@ -11041,6 +11177,13 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; }
+ ret = hclge_tp_port_init(hdev); + if (ret) { + dev_err(&pdev->dev, "failed to init tp port, ret = %d\n", + ret); + return ret; + } + ret = hclge_config_tso(hdev, HCLGE_TSO_MSS_MIN, HCLGE_TSO_MSS_MAX); if (ret) { dev_err(&pdev->dev, "Enable tso fail, ret =%d\n", ret); @@ -11995,6 +12138,8 @@ static const struct hnae3_ae_ops hclge_ops = { .add_cls_flower = hclge_add_cls_flower, .del_cls_flower = hclge_del_cls_flower, .cls_flower_active = hclge_is_cls_flower_active, + .get_phy_link_ksettings = hclge_get_phy_link_ksettings, + .set_phy_link_ksettings = hclge_set_phy_link_ksettings, };
static struct hnae3_ae_algo ae_algo = {
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 57a8f46b1bd3f5f43b06f48aab7c1f7ca0936be3 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
When the imp-controlled PHYs feature is enabled, phydev is NULL. In this case, the autoneg is always off when user uses ethtool -a command to get pause parameters because hclge_get_pauseparam() uses phydev to check whether device is TP port. To fit this new feature, use media type to check whether device is TP port.
And when user set pause parameters, these parameters need to always set to mac, no matter whether autoneg is off.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3905fa933bc9..7a50f517acbe 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -10158,9 +10158,10 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg, { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - struct phy_device *phydev = hdev->hw.mac.phydev; + u8 media_type = hdev->hw.mac.media_type;
- *auto_neg = phydev ? hclge_get_autoneg(handle) : 0; + *auto_neg = (media_type == HNAE3_MEDIA_TYPE_COPPER) ? + hclge_get_autoneg(handle) : 0;
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) { *rx_en = 0; @@ -10206,7 +10207,7 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg, struct phy_device *phydev = hdev->hw.mac.phydev; u32 fc_autoneg;
- if (phydev) { + if (phydev || hnae3_dev_phy_imp_supported(hdev)) { fc_autoneg = hclge_get_autoneg(handle); if (auto_neg != fc_autoneg) { dev_info(&hdev->pdev->dev, @@ -10225,7 +10226,7 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
hclge_record_user_pauseparam(hdev, rx_en, tx_en);
- if (!auto_neg) + if (!auto_neg || hnae3_dev_phy_imp_supported(hdev)) return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
if (phydev)
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 024712f51e5711d69ced729fb3398819ed6e8b53 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
When the imp-controlled PHYs feature is enabled, driver will not register mdio bus. In order to support ioctl ops for phy tool to read or write phy register in this case, the firmware implement a new command for driver and driver implement ioctl by using this new command.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 8 ++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 25 +++++++++++- .../hisilicon/hns3/hns3pf/hclge_mdio.c | 39 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_mdio.h | 2 + 4 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index f45ceaa8126f..abeacc990a9b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -306,6 +306,7 @@ enum hclge_opcode_type {
/* PHY command */ HCLGE_OPC_PHY_LINK_KSETTING = 0x7025, + HCLGE_OPC_PHY_REG = 0x7026, };
#define HCLGE_TQP_REG_OFFSET 0x80000 @@ -1166,6 +1167,13 @@ struct hclge_phy_link_ksetting_1_cmd { u8 rsv[22]; };
+struct hclge_phy_reg_cmd { + __le16 reg_addr; + u8 rsv0[2]; + __le16 reg_val; + u8 rsv1[18]; +}; + int hclge_cmd_init(struct hclge_dev *hdev); static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 7a50f517acbe..abeaebda7fc4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8904,6 +8904,29 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p, return 0; }
+static int hclge_mii_ioctl(struct hclge_dev *hdev, struct ifreq *ifr, int cmd) +{ + struct mii_ioctl_data *data = if_mii(ifr); + + if (!hnae3_dev_phy_imp_supported(hdev)) + return -EOPNOTSUPP; + + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = hdev->hw.mac.phy_addr; + /* this command reads phy id and register at the same time */ + fallthrough; + case SIOCGMIIREG: + data->val_out = hclge_read_phy_reg(hdev, data->reg_num); + return 0; + + case SIOCSMIIREG: + return hclge_write_phy_reg(hdev, data->reg_num, data->val_in); + default: + return -EOPNOTSUPP; + } +} + static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, int cmd) { @@ -8911,7 +8934,7 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, struct hclge_dev *hdev = vport->back;
if (!hdev->hw.mac.phydev) - return -EOPNOTSUPP; + return hclge_mii_ioctl(hdev, ifr, cmd);
return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index c194bba187d6..1231c34f0949 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -270,3 +270,42 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev)
phy_stop(phydev); } + +u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr) +{ + struct hclge_phy_reg_cmd *req; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, true); + + req = (struct hclge_phy_reg_cmd *)desc.data; + req->reg_addr = cpu_to_le16(reg_addr); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to read phy reg, ret = %d.\n", ret); + + return le16_to_cpu(req->reg_val); +} + +int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val) +{ + struct hclge_phy_reg_cmd *req; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, false); + + req = (struct hclge_phy_reg_cmd *)desc.data; + req->reg_addr = cpu_to_le16(reg_addr); + req->reg_val = cpu_to_le16(val); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to write phy reg, ret = %d.\n", ret); + + return ret; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h index dd9a1218a7b0..fd0e20190b90 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h @@ -9,5 +9,7 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle); void hclge_mac_disconnect_phy(struct hnae3_handle *handle); void hclge_mac_start_phy(struct hclge_dev *hdev); void hclge_mac_stop_phy(struct hclge_dev *hdev); +u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr); +int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val);
#endif
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit b47cfe1f402dbf10279b8f12131388fdff9d2259 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
If the imp-controlled PHYs feature is enabled, driver can not call phy driver interface to set loopback anymore and needs to send command to firmware to start phy loopback.
Driver reuses the existing firmware command 0x0315 to start phy loopback, just add a setting bit in this command. As this command is not only for serdes loopback anymore, rename this command to "xxx_COMMON_LOOPBACK", and modify function name, macro name and logs related to it.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 9 +-- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 20 ++++--- .../hisilicon/hns3/hns3pf/hclge_main.c | 58 +++++++++++-------- 3 files changed, 51 insertions(+), 36 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index abeacc990a9b..804f4c8360cf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -127,7 +127,7 @@ enum hclge_opcode_type { HCLGE_OPC_QUERY_MAC_TNL_INT = 0x0310, HCLGE_OPC_MAC_TNL_INT_EN = 0x0311, HCLGE_OPC_CLEAR_MAC_TNL_INT = 0x0312, - HCLGE_OPC_SERDES_LOOPBACK = 0x0315, + HCLGE_OPC_COMMON_LOOPBACK = 0x0315, HCLGE_OPC_CONFIG_FEC_MODE = 0x031A,
/* PFC/Pause commands */ @@ -964,9 +964,10 @@ struct hclge_pf_rst_done_cmd {
#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0) #define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2) -#define HCLGE_CMD_SERDES_DONE_B BIT(0) -#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1) -struct hclge_serdes_lb_cmd { +#define HCLGE_CMD_GE_PHY_INNER_LOOP_B BIT(3) +#define HCLGE_CMD_COMMON_LB_DONE_B BIT(0) +#define HCLGE_CMD_COMMON_LB_SUCCESS_B BIT(1) +struct hclge_common_lb_cmd { u8 mask; u8 enable; u8 result; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 6b1d197df881..1c699131e8df 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1546,13 +1546,13 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev, { struct phy_device *phydev = hdev->hw.mac.phydev; struct hclge_config_mac_mode_cmd *req_app; - struct hclge_serdes_lb_cmd *req_serdes; + struct hclge_common_lb_cmd *req_common; struct hclge_desc desc; u8 loopback_en; int ret;
req_app = (struct hclge_config_mac_mode_cmd *)desc.data; - req_serdes = (struct hclge_serdes_lb_cmd *)desc.data; + req_common = (struct hclge_common_lb_cmd *)desc.data;
dev_info(&hdev->pdev->dev, "mac id: %u\n", hdev->hw.mac.mac_id);
@@ -1569,27 +1569,33 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev, dev_info(&hdev->pdev->dev, "app loopback: %s\n", loopback_en ? "on" : "off");
- hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, true); + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "failed to dump serdes loopback status, ret = %d\n", + "failed to dump common loopback status, ret = %d\n", ret); return; }
- loopback_en = req_serdes->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; + loopback_en = req_common->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; dev_info(&hdev->pdev->dev, "serdes serial loopback: %s\n", loopback_en ? "on" : "off");
- loopback_en = req_serdes->enable & + loopback_en = req_common->enable & HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B; dev_info(&hdev->pdev->dev, "serdes parallel loopback: %s\n", loopback_en ? "on" : "off");
- if (phydev) + if (phydev) { dev_info(&hdev->pdev->dev, "phy loopback: %s\n", phydev->loopback_enabled ? "on" : "off"); + } else if (hnae3_dev_phy_imp_supported(hdev)) { + loopback_en = req_common->enable & + HCLGE_CMD_GE_PHY_INNER_LOOP_B; + dev_info(&hdev->pdev->dev, "phy loopback: %s\n", + loopback_en ? "on" : "off"); + } }
/* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index abeaebda7fc4..7461dcb702db 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -751,8 +751,9 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK; handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
- if (hdev->hw.mac.phydev && hdev->hw.mac.phydev->drv && - hdev->hw.mac.phydev->drv->set_loopback) { + if ((hdev->hw.mac.phydev && hdev->hw.mac.phydev->drv && + hdev->hw.mac.phydev->drv->set_loopback) || + hnae3_dev_phy_imp_supported(hdev)) { count += 1; handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK; } @@ -7270,19 +7271,19 @@ static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en) return ret; }
-static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en, +static int hclge_cfg_common_loopback(struct hclge_dev *hdev, bool en, enum hnae3_loop loop_mode) { -#define HCLGE_SERDES_RETRY_MS 10 -#define HCLGE_SERDES_RETRY_NUM 100 +#define HCLGE_COMMON_LB_RETRY_MS 10 +#define HCLGE_COMMON_LB_RETRY_NUM 100
- struct hclge_serdes_lb_cmd *req; + struct hclge_common_lb_cmd *req; struct hclge_desc desc; int ret, i = 0; u8 loop_mode_b;
- req = (struct hclge_serdes_lb_cmd *)desc.data; - hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false); + req = (struct hclge_common_lb_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, false);
switch (loop_mode) { case HNAE3_LOOP_SERIAL_SERDES: @@ -7291,9 +7292,12 @@ static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en, case HNAE3_LOOP_PARALLEL_SERDES: loop_mode_b = HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B; break; + case HNAE3_LOOP_PHY: + loop_mode_b = HCLGE_CMD_GE_PHY_INNER_LOOP_B; + break; default: dev_err(&hdev->pdev->dev, - "unsupported serdes loopback mode %d\n", loop_mode); + "unsupported common loopback mode %d\n", loop_mode); return -ENOTSUPP; }
@@ -7307,39 +7311,39 @@ static int hclge_cfg_serdes_loopback(struct hclge_dev *hdev, bool en, ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "serdes loopback set fail, ret = %d\n", ret); + "common loopback set fail, ret = %d\n", ret); return ret; }
do { - msleep(HCLGE_SERDES_RETRY_MS); - hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, + msleep(HCLGE_COMMON_LB_RETRY_MS); + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "serdes loopback get, ret = %d\n", ret); + "common loopback get, ret = %d\n", ret); return ret; } - } while (++i < HCLGE_SERDES_RETRY_NUM && - !(req->result & HCLGE_CMD_SERDES_DONE_B)); + } while (++i < HCLGE_COMMON_LB_RETRY_NUM && + !(req->result & HCLGE_CMD_COMMON_LB_DONE_B));
- if (!(req->result & HCLGE_CMD_SERDES_DONE_B)) { - dev_err(&hdev->pdev->dev, "serdes loopback set timeout\n"); + if (!(req->result & HCLGE_CMD_COMMON_LB_DONE_B)) { + dev_err(&hdev->pdev->dev, "common loopback set timeout\n"); return -EBUSY; - } else if (!(req->result & HCLGE_CMD_SERDES_SUCCESS_B)) { - dev_err(&hdev->pdev->dev, "serdes loopback set failed in fw\n"); + } else if (!(req->result & HCLGE_CMD_COMMON_LB_SUCCESS_B)) { + dev_err(&hdev->pdev->dev, "common loopback set failed in fw\n"); return -EIO; } return ret; }
-static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, +static int hclge_set_common_loopback(struct hclge_dev *hdev, bool en, enum hnae3_loop loop_mode) { int ret;
- ret = hclge_cfg_serdes_loopback(hdev, en, loop_mode); + ret = hclge_cfg_common_loopback(hdev, en, loop_mode); if (ret) return ret;
@@ -7388,8 +7392,12 @@ static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en) struct phy_device *phydev = hdev->hw.mac.phydev; int ret;
- if (!phydev) + if (!phydev) { + if (hnae3_dev_phy_imp_supported(hdev)) + return hclge_set_common_loopback(hdev, en, + HNAE3_LOOP_PHY); return -ENOTSUPP; + }
if (en) ret = hclge_enable_phy_loopback(hdev, phydev); @@ -7460,7 +7468,7 @@ static int hclge_set_loopback(struct hnae3_handle *handle, break; case HNAE3_LOOP_SERIAL_SERDES: case HNAE3_LOOP_PARALLEL_SERDES: - ret = hclge_set_serdes_loopback(hdev, en, loop_mode); + ret = hclge_set_common_loopback(hdev, en, loop_mode); break; case HNAE3_LOOP_PHY: ret = hclge_set_phy_loopback(hdev, en); @@ -7493,11 +7501,11 @@ static int hclge_set_default_loopback(struct hclge_dev *hdev) if (ret) return ret;
- ret = hclge_cfg_serdes_loopback(hdev, false, HNAE3_LOOP_SERIAL_SERDES); + ret = hclge_cfg_common_loopback(hdev, false, HNAE3_LOOP_SERIAL_SERDES); if (ret) return ret;
- return hclge_cfg_serdes_loopback(hdev, false, + return hclge_cfg_common_loopback(hdev, false, HNAE3_LOOP_PARALLEL_SERDES); }
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 5f2b1238b33c38478ddc55536b65277b30f5d456 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The process of function hclge_add_fd_entry() is complex and prolix. To make it more readable, extract the process of fs->ring_cookie to a single function.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 67 +++++++++++-------- 1 file changed, 40 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 7461dcb702db..683ac1d881b0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6126,6 +6126,42 @@ static bool hclge_is_cls_flower_active(struct hnae3_handle *handle) return hdev->fd_active_type == HCLGE_FD_TC_FLOWER_ACTIVE; }
+static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie, + u16 *vport_id, u8 *action, u16 *queue_id) +{ + struct hclge_vport *vport = hdev->vport; + + if (ring_cookie == RX_CLS_FLOW_DISC) { + *action = HCLGE_FD_ACTION_DROP_PACKET; + } else { + u32 ring = ethtool_get_flow_spec_ring(ring_cookie); + u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie); + u16 tqps; + + if (vf > hdev->num_req_vfs) { + dev_err(&hdev->pdev->dev, + "Error: vf id (%u) > max vf num (%u)\n", + vf, hdev->num_req_vfs); + return -EINVAL; + } + + *vport_id = vf ? hdev->vport[vf].vport_id : vport->vport_id; + tqps = hdev->vport[vf].nic.kinfo.num_tqps; + + if (ring >= tqps) { + dev_err(&hdev->pdev->dev, + "Error: queue id (%u) > max tqp num (%u)\n", + ring, tqps - 1); + return -EINVAL; + } + + *action = HCLGE_FD_ACTION_SELECT_QUEUE; + *queue_id = ring; + } + + return 0; +} + static int hclge_add_fd_entry(struct hnae3_handle *handle, struct ethtool_rxnfc *cmd) { @@ -6162,33 +6198,10 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, if (ret) return ret;
- if (fs->ring_cookie == RX_CLS_FLOW_DISC) { - action = HCLGE_FD_ACTION_DROP_PACKET; - } else { - u32 ring = ethtool_get_flow_spec_ring(fs->ring_cookie); - u8 vf = ethtool_get_flow_spec_ring_vf(fs->ring_cookie); - u16 tqps; - - if (vf > hdev->num_req_vfs) { - dev_err(&hdev->pdev->dev, - "Error: vf id (%u) > max vf num (%u)\n", - vf, hdev->num_req_vfs); - return -EINVAL; - } - - dst_vport_id = vf ? hdev->vport[vf].vport_id : vport->vport_id; - tqps = vf ? hdev->vport[vf].alloc_tqps : vport->alloc_tqps; - - if (ring >= tqps) { - dev_err(&hdev->pdev->dev, - "Error: queue id (%u) > max tqp num (%u)\n", - ring, tqps - 1); - return -EINVAL; - } - - action = HCLGE_FD_ACTION_SELECT_QUEUE; - q_index = ring; - } + ret = hclge_fd_parse_ring_cookie(hdev, fs->ring_cookie, &dst_vport_id, + &action, &q_index); + if (ret) + return ret;
rule = kzalloc(sizeof(*rule), GFP_KERNEL); if (!rule)
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 74b755d1dbf1c4ff6f0cc4513e573eb15c0e7dfc category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The process of function hclge_fd_get_tuple() is complex and prolix. To make it more readable, extract the process of each flow-type tuple to a single function.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 220 ++++++++++-------- 1 file changed, 117 insertions(+), 103 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 683ac1d881b0..9c0e8970f230 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5935,144 +5935,158 @@ static int hclge_fd_update_rule_list(struct hclge_dev *hdev, return 0; }
-static int hclge_fd_get_tuple(struct hclge_dev *hdev, - struct ethtool_rx_flow_spec *fs, - struct hclge_fd_rule *rule) +static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule, u8 ip_proto) { - u32 flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT); + rule->tuples.src_ip[IPV4_INDEX] = + be32_to_cpu(fs->h_u.tcp_ip4_spec.ip4src); + rule->tuples_mask.src_ip[IPV4_INDEX] = + be32_to_cpu(fs->m_u.tcp_ip4_spec.ip4src);
- switch (flow_type) { - case SCTP_V4_FLOW: - case TCP_V4_FLOW: - case UDP_V4_FLOW: - rule->tuples.src_ip[IPV4_INDEX] = - be32_to_cpu(fs->h_u.tcp_ip4_spec.ip4src); - rule->tuples_mask.src_ip[IPV4_INDEX] = - be32_to_cpu(fs->m_u.tcp_ip4_spec.ip4src); + rule->tuples.dst_ip[IPV4_INDEX] = + be32_to_cpu(fs->h_u.tcp_ip4_spec.ip4dst); + rule->tuples_mask.dst_ip[IPV4_INDEX] = + be32_to_cpu(fs->m_u.tcp_ip4_spec.ip4dst);
- rule->tuples.dst_ip[IPV4_INDEX] = - be32_to_cpu(fs->h_u.tcp_ip4_spec.ip4dst); - rule->tuples_mask.dst_ip[IPV4_INDEX] = - be32_to_cpu(fs->m_u.tcp_ip4_spec.ip4dst); + rule->tuples.src_port = be16_to_cpu(fs->h_u.tcp_ip4_spec.psrc); + rule->tuples_mask.src_port = be16_to_cpu(fs->m_u.tcp_ip4_spec.psrc);
- rule->tuples.src_port = be16_to_cpu(fs->h_u.tcp_ip4_spec.psrc); - rule->tuples_mask.src_port = - be16_to_cpu(fs->m_u.tcp_ip4_spec.psrc); + rule->tuples.dst_port = be16_to_cpu(fs->h_u.tcp_ip4_spec.pdst); + rule->tuples_mask.dst_port = be16_to_cpu(fs->m_u.tcp_ip4_spec.pdst);
- rule->tuples.dst_port = be16_to_cpu(fs->h_u.tcp_ip4_spec.pdst); - rule->tuples_mask.dst_port = - be16_to_cpu(fs->m_u.tcp_ip4_spec.pdst); + rule->tuples.ip_tos = fs->h_u.tcp_ip4_spec.tos; + rule->tuples_mask.ip_tos = fs->m_u.tcp_ip4_spec.tos;
- rule->tuples.ip_tos = fs->h_u.tcp_ip4_spec.tos; - rule->tuples_mask.ip_tos = fs->m_u.tcp_ip4_spec.tos; + rule->tuples.ether_proto = ETH_P_IP; + rule->tuples_mask.ether_proto = 0xFFFF;
- rule->tuples.ether_proto = ETH_P_IP; - rule->tuples_mask.ether_proto = 0xFFFF; + rule->tuples.ip_proto = ip_proto; + rule->tuples_mask.ip_proto = 0xFF; +}
- break; - case IP_USER_FLOW: - rule->tuples.src_ip[IPV4_INDEX] = - be32_to_cpu(fs->h_u.usr_ip4_spec.ip4src); - rule->tuples_mask.src_ip[IPV4_INDEX] = - be32_to_cpu(fs->m_u.usr_ip4_spec.ip4src); +static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule) +{ + rule->tuples.src_ip[IPV4_INDEX] = + be32_to_cpu(fs->h_u.usr_ip4_spec.ip4src); + rule->tuples_mask.src_ip[IPV4_INDEX] = + be32_to_cpu(fs->m_u.usr_ip4_spec.ip4src);
- rule->tuples.dst_ip[IPV4_INDEX] = - be32_to_cpu(fs->h_u.usr_ip4_spec.ip4dst); - rule->tuples_mask.dst_ip[IPV4_INDEX] = - be32_to_cpu(fs->m_u.usr_ip4_spec.ip4dst); + rule->tuples.dst_ip[IPV4_INDEX] = + be32_to_cpu(fs->h_u.usr_ip4_spec.ip4dst); + rule->tuples_mask.dst_ip[IPV4_INDEX] = + be32_to_cpu(fs->m_u.usr_ip4_spec.ip4dst);
- rule->tuples.ip_tos = fs->h_u.usr_ip4_spec.tos; - rule->tuples_mask.ip_tos = fs->m_u.usr_ip4_spec.tos; + rule->tuples.ip_tos = fs->h_u.usr_ip4_spec.tos; + rule->tuples_mask.ip_tos = fs->m_u.usr_ip4_spec.tos;
- rule->tuples.ip_proto = fs->h_u.usr_ip4_spec.proto; - rule->tuples_mask.ip_proto = fs->m_u.usr_ip4_spec.proto; + rule->tuples.ip_proto = fs->h_u.usr_ip4_spec.proto; + rule->tuples_mask.ip_proto = fs->m_u.usr_ip4_spec.proto;
- rule->tuples.ether_proto = ETH_P_IP; - rule->tuples_mask.ether_proto = 0xFFFF; + rule->tuples.ether_proto = ETH_P_IP; + rule->tuples_mask.ether_proto = 0xFFFF; +}
- break; - case SCTP_V6_FLOW: - case TCP_V6_FLOW: - case UDP_V6_FLOW: - be32_to_cpu_array(rule->tuples.src_ip, - fs->h_u.tcp_ip6_spec.ip6src, IPV6_SIZE); - be32_to_cpu_array(rule->tuples_mask.src_ip, - fs->m_u.tcp_ip6_spec.ip6src, IPV6_SIZE); +static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule, u8 ip_proto) +{ + be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.tcp_ip6_spec.ip6src, + IPV6_SIZE); + be32_to_cpu_array(rule->tuples_mask.src_ip, fs->m_u.tcp_ip6_spec.ip6src, + IPV6_SIZE);
- be32_to_cpu_array(rule->tuples.dst_ip, - fs->h_u.tcp_ip6_spec.ip6dst, IPV6_SIZE); - be32_to_cpu_array(rule->tuples_mask.dst_ip, - fs->m_u.tcp_ip6_spec.ip6dst, IPV6_SIZE); + be32_to_cpu_array(rule->tuples.dst_ip, fs->h_u.tcp_ip6_spec.ip6dst, + IPV6_SIZE); + be32_to_cpu_array(rule->tuples_mask.dst_ip, fs->m_u.tcp_ip6_spec.ip6dst, + IPV6_SIZE);
- rule->tuples.src_port = be16_to_cpu(fs->h_u.tcp_ip6_spec.psrc); - rule->tuples_mask.src_port = - be16_to_cpu(fs->m_u.tcp_ip6_spec.psrc); + rule->tuples.src_port = be16_to_cpu(fs->h_u.tcp_ip6_spec.psrc); + rule->tuples_mask.src_port = be16_to_cpu(fs->m_u.tcp_ip6_spec.psrc);
- rule->tuples.dst_port = be16_to_cpu(fs->h_u.tcp_ip6_spec.pdst); - rule->tuples_mask.dst_port = - be16_to_cpu(fs->m_u.tcp_ip6_spec.pdst); + rule->tuples.dst_port = be16_to_cpu(fs->h_u.tcp_ip6_spec.pdst); + rule->tuples_mask.dst_port = be16_to_cpu(fs->m_u.tcp_ip6_spec.pdst);
- rule->tuples.ether_proto = ETH_P_IPV6; - rule->tuples_mask.ether_proto = 0xFFFF; + rule->tuples.ether_proto = ETH_P_IPV6; + rule->tuples_mask.ether_proto = 0xFFFF;
- break; - case IPV6_USER_FLOW: - be32_to_cpu_array(rule->tuples.src_ip, - fs->h_u.usr_ip6_spec.ip6src, IPV6_SIZE); - be32_to_cpu_array(rule->tuples_mask.src_ip, - fs->m_u.usr_ip6_spec.ip6src, IPV6_SIZE); + rule->tuples.ip_proto = ip_proto; + rule->tuples_mask.ip_proto = 0xFF; +}
- be32_to_cpu_array(rule->tuples.dst_ip, - fs->h_u.usr_ip6_spec.ip6dst, IPV6_SIZE); - be32_to_cpu_array(rule->tuples_mask.dst_ip, - fs->m_u.usr_ip6_spec.ip6dst, IPV6_SIZE); +static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule) +{ + be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.usr_ip6_spec.ip6src, + IPV6_SIZE); + be32_to_cpu_array(rule->tuples_mask.src_ip, fs->m_u.usr_ip6_spec.ip6src, + IPV6_SIZE);
- rule->tuples.ip_proto = fs->h_u.usr_ip6_spec.l4_proto; - rule->tuples_mask.ip_proto = fs->m_u.usr_ip6_spec.l4_proto; + be32_to_cpu_array(rule->tuples.dst_ip, fs->h_u.usr_ip6_spec.ip6dst, + IPV6_SIZE); + be32_to_cpu_array(rule->tuples_mask.dst_ip, fs->m_u.usr_ip6_spec.ip6dst, + IPV6_SIZE);
- rule->tuples.ether_proto = ETH_P_IPV6; - rule->tuples_mask.ether_proto = 0xFFFF; + rule->tuples.ip_proto = fs->h_u.usr_ip6_spec.l4_proto; + rule->tuples_mask.ip_proto = fs->m_u.usr_ip6_spec.l4_proto;
- break; - case ETHER_FLOW: - ether_addr_copy(rule->tuples.src_mac, - fs->h_u.ether_spec.h_source); - ether_addr_copy(rule->tuples_mask.src_mac, - fs->m_u.ether_spec.h_source); + rule->tuples.ether_proto = ETH_P_IPV6; + rule->tuples_mask.ether_proto = 0xFFFF; +}
- ether_addr_copy(rule->tuples.dst_mac, - fs->h_u.ether_spec.h_dest); - ether_addr_copy(rule->tuples_mask.dst_mac, - fs->m_u.ether_spec.h_dest); +static void hclge_fd_get_ether_tuple(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule) +{ + ether_addr_copy(rule->tuples.src_mac, fs->h_u.ether_spec.h_source); + ether_addr_copy(rule->tuples_mask.src_mac, fs->m_u.ether_spec.h_source);
- rule->tuples.ether_proto = - be16_to_cpu(fs->h_u.ether_spec.h_proto); - rule->tuples_mask.ether_proto = - be16_to_cpu(fs->m_u.ether_spec.h_proto); + ether_addr_copy(rule->tuples.dst_mac, fs->h_u.ether_spec.h_dest); + ether_addr_copy(rule->tuples_mask.dst_mac, fs->m_u.ether_spec.h_dest);
- break; - default: - return -EOPNOTSUPP; - } + rule->tuples.ether_proto = be16_to_cpu(fs->h_u.ether_spec.h_proto); + rule->tuples_mask.ether_proto = be16_to_cpu(fs->m_u.ether_spec.h_proto); +} + +static int hclge_fd_get_tuple(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule) +{ + u32 flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT);
switch (flow_type) { case SCTP_V4_FLOW: - case SCTP_V6_FLOW: - rule->tuples.ip_proto = IPPROTO_SCTP; - rule->tuples_mask.ip_proto = 0xFF; + hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_SCTP); break; case TCP_V4_FLOW: - case TCP_V6_FLOW: - rule->tuples.ip_proto = IPPROTO_TCP; - rule->tuples_mask.ip_proto = 0xFF; + hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_TCP); break; case UDP_V4_FLOW: + hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_UDP); + break; + case IP_USER_FLOW: + hclge_fd_get_ip4_tuple(hdev, fs, rule); + break; + case SCTP_V6_FLOW: + hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_SCTP); + break; + case TCP_V6_FLOW: + hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_TCP); + break; case UDP_V6_FLOW: - rule->tuples.ip_proto = IPPROTO_UDP; - rule->tuples_mask.ip_proto = 0xFF; + hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_UDP); break; - default: + case IPV6_USER_FLOW: + hclge_fd_get_ip6_tuple(hdev, fs, rule); break; + case ETHER_FLOW: + hclge_fd_get_ether_tuple(hdev, fs, rule); + break; + default: + return -EOPNOTSUPP; }
if (fs->flow_type & FLOW_EXT) {
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit fb72699dfef8706abe203ec8c8fc69a023c161ce category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, there are too many branches for hclge_fd_convert_tuple(). And it may be more when add new tuples. Refactor it by sorting the tuples according to their length. So it only needs several KEY_OPT now, and being flexible to add new tuples.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 189 ++++++++---------- .../hisilicon/hns3/hns3pf/hclge_main.h | 12 ++ 2 files changed, 97 insertions(+), 104 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9c0e8970f230..8f4b6f26469f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -384,36 +384,56 @@ static const struct key_info meta_data_key_info[] = { };
static const struct key_info tuple_key_info[] = { - { OUTER_DST_MAC, 48}, - { OUTER_SRC_MAC, 48}, - { OUTER_VLAN_TAG_FST, 16}, - { OUTER_VLAN_TAG_SEC, 16}, - { OUTER_ETH_TYPE, 16}, - { OUTER_L2_RSV, 16}, - { OUTER_IP_TOS, 8}, - { OUTER_IP_PROTO, 8}, - { OUTER_SRC_IP, 32}, - { OUTER_DST_IP, 32}, - { OUTER_L3_RSV, 16}, - { OUTER_SRC_PORT, 16}, - { OUTER_DST_PORT, 16}, - { OUTER_L4_RSV, 32}, - { OUTER_TUN_VNI, 24}, - { OUTER_TUN_FLOW_ID, 8}, - { INNER_DST_MAC, 48}, - { INNER_SRC_MAC, 48}, - { INNER_VLAN_TAG_FST, 16}, - { INNER_VLAN_TAG_SEC, 16}, - { INNER_ETH_TYPE, 16}, - { INNER_L2_RSV, 16}, - { INNER_IP_TOS, 8}, - { INNER_IP_PROTO, 8}, - { INNER_SRC_IP, 32}, - { INNER_DST_IP, 32}, - { INNER_L3_RSV, 16}, - { INNER_SRC_PORT, 16}, - { INNER_DST_PORT, 16}, - { INNER_L4_RSV, 32}, + { OUTER_DST_MAC, 48, KEY_OPT_MAC, -1, -1 }, + { OUTER_SRC_MAC, 48, KEY_OPT_MAC, -1, -1 }, + { OUTER_VLAN_TAG_FST, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_VLAN_TAG_SEC, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_ETH_TYPE, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_L2_RSV, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_IP_TOS, 8, KEY_OPT_U8, -1, -1 }, + { OUTER_IP_PROTO, 8, KEY_OPT_U8, -1, -1 }, + { OUTER_SRC_IP, 32, KEY_OPT_IP, -1, -1 }, + { OUTER_DST_IP, 32, KEY_OPT_IP, -1, -1 }, + { OUTER_L3_RSV, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_SRC_PORT, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_DST_PORT, 16, KEY_OPT_LE16, -1, -1 }, + { OUTER_L4_RSV, 32, KEY_OPT_LE32, -1, -1 }, + { OUTER_TUN_VNI, 24, KEY_OPT_VNI, -1, -1 }, + { OUTER_TUN_FLOW_ID, 8, KEY_OPT_U8, -1, -1 }, + { INNER_DST_MAC, 48, KEY_OPT_MAC, + offsetof(struct hclge_fd_rule, tuples.dst_mac), + offsetof(struct hclge_fd_rule, tuples_mask.dst_mac) }, + { INNER_SRC_MAC, 48, KEY_OPT_MAC, + offsetof(struct hclge_fd_rule, tuples.src_mac), + offsetof(struct hclge_fd_rule, tuples_mask.src_mac) }, + { INNER_VLAN_TAG_FST, 16, KEY_OPT_LE16, + offsetof(struct hclge_fd_rule, tuples.vlan_tag1), + offsetof(struct hclge_fd_rule, tuples_mask.vlan_tag1) }, + { INNER_VLAN_TAG_SEC, 16, KEY_OPT_LE16, -1, -1 }, + { INNER_ETH_TYPE, 16, KEY_OPT_LE16, + offsetof(struct hclge_fd_rule, tuples.ether_proto), + offsetof(struct hclge_fd_rule, tuples_mask.ether_proto) }, + { INNER_L2_RSV, 16, KEY_OPT_LE16, -1, -1 }, + { INNER_IP_TOS, 8, KEY_OPT_U8, + offsetof(struct hclge_fd_rule, tuples.ip_tos), + offsetof(struct hclge_fd_rule, tuples_mask.ip_tos) }, + { INNER_IP_PROTO, 8, KEY_OPT_U8, + offsetof(struct hclge_fd_rule, tuples.ip_proto), + offsetof(struct hclge_fd_rule, tuples_mask.ip_proto) }, + { INNER_SRC_IP, 32, KEY_OPT_IP, + offsetof(struct hclge_fd_rule, tuples.src_ip), + offsetof(struct hclge_fd_rule, tuples_mask.src_ip) }, + { INNER_DST_IP, 32, KEY_OPT_IP, + offsetof(struct hclge_fd_rule, tuples.dst_ip), + offsetof(struct hclge_fd_rule, tuples_mask.dst_ip) }, + { INNER_L3_RSV, 16, KEY_OPT_LE16, -1, -1 }, + { INNER_SRC_PORT, 16, KEY_OPT_LE16, + offsetof(struct hclge_fd_rule, tuples.src_port), + offsetof(struct hclge_fd_rule, tuples_mask.src_port) }, + { INNER_DST_PORT, 16, KEY_OPT_LE16, + offsetof(struct hclge_fd_rule, tuples.dst_port), + offsetof(struct hclge_fd_rule, tuples_mask.dst_port) }, + { INNER_L4_RSV, 32, KEY_OPT_LE32, -1, -1 }, };
static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) @@ -5371,96 +5391,57 @@ static int hclge_fd_ad_config(struct hclge_dev *hdev, u8 stage, int loc, static bool hclge_fd_convert_tuple(u32 tuple_bit, u8 *key_x, u8 *key_y, struct hclge_fd_rule *rule) { + int offset, moffset, ip_offset; + enum HCLGE_FD_KEY_OPT key_opt; u16 tmp_x_s, tmp_y_s; u32 tmp_x_l, tmp_y_l; + u8 *p = (u8 *)rule; int i;
- if (rule->unused_tuple & tuple_bit) + if (rule->unused_tuple & BIT(tuple_bit)) return true;
- switch (tuple_bit) { - case BIT(INNER_DST_MAC): - for (i = 0; i < ETH_ALEN; i++) { - calc_x(key_x[ETH_ALEN - 1 - i], rule->tuples.dst_mac[i], - rule->tuples_mask.dst_mac[i]); - calc_y(key_y[ETH_ALEN - 1 - i], rule->tuples.dst_mac[i], - rule->tuples_mask.dst_mac[i]); - } + key_opt = tuple_key_info[tuple_bit].key_opt; + offset = tuple_key_info[tuple_bit].offset; + moffset = tuple_key_info[tuple_bit].moffset;
- return true; - case BIT(INNER_SRC_MAC): - for (i = 0; i < ETH_ALEN; i++) { - calc_x(key_x[ETH_ALEN - 1 - i], rule->tuples.src_mac[i], - rule->tuples_mask.src_mac[i]); - calc_y(key_y[ETH_ALEN - 1 - i], rule->tuples.src_mac[i], - rule->tuples_mask.src_mac[i]); - } + switch (key_opt) { + case KEY_OPT_U8: + calc_x(*key_x, p[offset], p[moffset]); + calc_y(*key_y, p[offset], p[moffset]);
return true; - case BIT(INNER_VLAN_TAG_FST): - calc_x(tmp_x_s, rule->tuples.vlan_tag1, - rule->tuples_mask.vlan_tag1); - calc_y(tmp_y_s, rule->tuples.vlan_tag1, - rule->tuples_mask.vlan_tag1); + case KEY_OPT_LE16: + calc_x(tmp_x_s, *(u16 *)(&p[offset]), *(u16 *)(&p[moffset])); + calc_y(tmp_y_s, *(u16 *)(&p[offset]), *(u16 *)(&p[moffset])); *(__le16 *)key_x = cpu_to_le16(tmp_x_s); *(__le16 *)key_y = cpu_to_le16(tmp_y_s);
return true; - case BIT(INNER_ETH_TYPE): - calc_x(tmp_x_s, rule->tuples.ether_proto, - rule->tuples_mask.ether_proto); - calc_y(tmp_y_s, rule->tuples.ether_proto, - rule->tuples_mask.ether_proto); - *(__le16 *)key_x = cpu_to_le16(tmp_x_s); - *(__le16 *)key_y = cpu_to_le16(tmp_y_s); - - return true; - case BIT(INNER_IP_TOS): - calc_x(*key_x, rule->tuples.ip_tos, rule->tuples_mask.ip_tos); - calc_y(*key_y, rule->tuples.ip_tos, rule->tuples_mask.ip_tos); - - return true; - case BIT(INNER_IP_PROTO): - calc_x(*key_x, rule->tuples.ip_proto, - rule->tuples_mask.ip_proto); - calc_y(*key_y, rule->tuples.ip_proto, - rule->tuples_mask.ip_proto); - - return true; - case BIT(INNER_SRC_IP): - calc_x(tmp_x_l, rule->tuples.src_ip[IPV4_INDEX], - rule->tuples_mask.src_ip[IPV4_INDEX]); - calc_y(tmp_y_l, rule->tuples.src_ip[IPV4_INDEX], - rule->tuples_mask.src_ip[IPV4_INDEX]); + case KEY_OPT_LE32: + calc_x(tmp_x_l, *(u32 *)(&p[offset]), *(u32 *)(&p[moffset])); + calc_y(tmp_y_l, *(u32 *)(&p[offset]), *(u32 *)(&p[moffset])); *(__le32 *)key_x = cpu_to_le32(tmp_x_l); *(__le32 *)key_y = cpu_to_le32(tmp_y_l);
return true; - case BIT(INNER_DST_IP): - calc_x(tmp_x_l, rule->tuples.dst_ip[IPV4_INDEX], - rule->tuples_mask.dst_ip[IPV4_INDEX]); - calc_y(tmp_y_l, rule->tuples.dst_ip[IPV4_INDEX], - rule->tuples_mask.dst_ip[IPV4_INDEX]); - *(__le32 *)key_x = cpu_to_le32(tmp_x_l); - *(__le32 *)key_y = cpu_to_le32(tmp_y_l); - - return true; - case BIT(INNER_SRC_PORT): - calc_x(tmp_x_s, rule->tuples.src_port, - rule->tuples_mask.src_port); - calc_y(tmp_y_s, rule->tuples.src_port, - rule->tuples_mask.src_port); - *(__le16 *)key_x = cpu_to_le16(tmp_x_s); - *(__le16 *)key_y = cpu_to_le16(tmp_y_s); + case KEY_OPT_MAC: + for (i = 0; i < ETH_ALEN; i++) { + calc_x(key_x[ETH_ALEN - 1 - i], p[offset + i], + p[moffset + i]); + calc_y(key_y[ETH_ALEN - 1 - i], p[offset + i], + p[moffset + i]); + }
return true; - case BIT(INNER_DST_PORT): - calc_x(tmp_x_s, rule->tuples.dst_port, - rule->tuples_mask.dst_port); - calc_y(tmp_y_s, rule->tuples.dst_port, - rule->tuples_mask.dst_port); - *(__le16 *)key_x = cpu_to_le16(tmp_x_s); - *(__le16 *)key_y = cpu_to_le16(tmp_y_s); + case KEY_OPT_IP: + ip_offset = IPV4_INDEX * sizeof(u32); + calc_x(tmp_x_l, *(u32 *)(&p[offset + ip_offset]), + *(u32 *)(&p[moffset + ip_offset])); + calc_y(tmp_y_l, *(u32 *)(&p[offset + ip_offset]), + *(u32 *)(&p[moffset + ip_offset])); + *(__le32 *)key_x = cpu_to_le32(tmp_x_l); + *(__le32 *)key_y = cpu_to_le32(tmp_y_l);
return true; default: @@ -5548,12 +5529,12 @@ static int hclge_config_key(struct hclge_dev *hdev, u8 stage,
for (i = 0 ; i < MAX_TUPLE; i++) { bool tuple_valid; - u32 check_tuple;
tuple_size = tuple_key_info[i].key_length / 8; - check_tuple = key_cfg->tuple_active & BIT(i); + if (!(key_cfg->tuple_active & BIT(i))) + continue;
- tuple_valid = hclge_fd_convert_tuple(check_tuple, cur_key_x, + tuple_valid = hclge_fd_convert_tuple(i, cur_key_x, cur_key_y, rule); if (tuple_valid) { cur_key_x += tuple_size; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 19d7f28773f3..6fe745538b30 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -548,9 +548,21 @@ enum HCLGE_FD_META_DATA { MAX_META_DATA, };
+enum HCLGE_FD_KEY_OPT { + KEY_OPT_U8, + KEY_OPT_LE16, + KEY_OPT_LE32, + KEY_OPT_MAC, + KEY_OPT_IP, + KEY_OPT_VNI, +}; + struct key_info { u8 key_type; u8 key_length; /* use bit as unit */ + enum HCLGE_FD_KEY_OPT key_opt; + int offset; + int moffset; };
#define MAX_KEY_LENGTH 400
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit ae4811913f576d3a891e2ca8a3ad11746f644c69 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The hardware supports to parse and match the traffic class field of IPv6 packet for flow director, uses the same tuple as ip tos. So removes the limitation of configure 'tclass' by driver.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 8f4b6f26469f..6f355df95ae5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5665,8 +5665,7 @@ static int hclge_fd_check_tcpip6_tuple(struct ethtool_tcpip6_spec *spec, if (!spec || !unused_tuple) return -EINVAL;
- *unused_tuple |= BIT(INNER_SRC_MAC) | BIT(INNER_DST_MAC) | - BIT(INNER_IP_TOS); + *unused_tuple |= BIT(INNER_SRC_MAC) | BIT(INNER_DST_MAC);
/* check whether src/dst ip address used */ if (ipv6_addr_any((struct in6_addr *)spec->ip6src)) @@ -5681,8 +5680,8 @@ static int hclge_fd_check_tcpip6_tuple(struct ethtool_tcpip6_spec *spec, if (!spec->pdst) *unused_tuple |= BIT(INNER_DST_PORT);
- if (spec->tclass) - return -EOPNOTSUPP; + if (!spec->tclass) + *unused_tuple |= BIT(INNER_IP_TOS);
return 0; } @@ -5694,7 +5693,7 @@ static int hclge_fd_check_ip6_tuple(struct ethtool_usrip6_spec *spec, return -EINVAL;
*unused_tuple |= BIT(INNER_SRC_MAC) | BIT(INNER_DST_MAC) | - BIT(INNER_IP_TOS) | BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT); + BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT);
/* check whether src/dst ip address used */ if (ipv6_addr_any((struct in6_addr *)spec->ip6src)) @@ -5706,8 +5705,8 @@ static int hclge_fd_check_ip6_tuple(struct ethtool_usrip6_spec *spec, if (!spec->l4_proto) *unused_tuple |= BIT(INNER_IP_PROTO);
- if (spec->tclass) - return -EOPNOTSUPP; + if (!spec->tclass) + *unused_tuple |= BIT(INNER_IP_TOS);
if (spec->l4_4_bytes) return -EOPNOTSUPP; @@ -5993,6 +5992,9 @@ static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev, rule->tuples.ether_proto = ETH_P_IPV6; rule->tuples_mask.ether_proto = 0xFFFF;
+ rule->tuples.ip_tos = fs->h_u.tcp_ip6_spec.tclass; + rule->tuples_mask.ip_tos = fs->m_u.tcp_ip6_spec.tclass; + rule->tuples.ip_proto = ip_proto; rule->tuples_mask.ip_proto = 0xFF; } @@ -6014,6 +6016,9 @@ static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev, rule->tuples.ip_proto = fs->h_u.usr_ip6_spec.l4_proto; rule->tuples_mask.ip_proto = fs->m_u.usr_ip6_spec.l4_proto;
+ rule->tuples.ip_tos = fs->h_u.tcp_ip6_spec.tclass; + rule->tuples_mask.ip_tos = fs->m_u.tcp_ip6_spec.tclass; + rule->tuples.ether_proto = ETH_P_IPV6; rule->tuples_mask.ether_proto = 0xFFFF; } @@ -6423,6 +6428,10 @@ static void hclge_fd_get_tcpip6_info(struct hclge_fd_rule *rule, cpu_to_be32_array(spec_mask->ip6dst, rule->tuples_mask.dst_ip, IPV6_SIZE);
+ spec->tclass = rule->tuples.ip_tos; + spec_mask->tclass = rule->unused_tuple & BIT(INNER_IP_TOS) ? + 0 : rule->tuples_mask.ip_tos; + spec->psrc = cpu_to_be16(rule->tuples.src_port); spec_mask->psrc = rule->unused_tuple & BIT(INNER_SRC_PORT) ? 0 : cpu_to_be16(rule->tuples_mask.src_port); @@ -6450,6 +6459,10 @@ static void hclge_fd_get_ip6_info(struct hclge_fd_rule *rule, cpu_to_be32_array(spec_mask->ip6dst, rule->tuples_mask.dst_ip, IPV6_SIZE);
+ spec->tclass = rule->tuples.ip_tos; + spec_mask->tclass = rule->unused_tuple & BIT(INNER_IP_TOS) ? + 0 : rule->tuples_mask.ip_tos; + spec->l4_proto = rule->tuples.ip_proto; spec_mask->l4_proto = rule->unused_tuple & BIT(INNER_IP_PROTO) ? 0 : rule->tuples_mask.ip_proto;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit fc4243b8de8b4e7170f07f2660dcab3f8ecda0e9 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the flow director rule of aRFS is configured in the IO path. It's time-consuming. So move out the configuration, and configure it asynchronously. And keep ethtool and tc flower rule using synchronous way, otherwise the application maybe unable to know the rule is installed or pending.
Add a state member for each flow director rule to indicate the rule state. There are 4 states: TO_ADD: the rule is waiting to add to hardware TO_DEL: the rule is waiting to remove from hardware DELETED: the rule has been removed from hardware. It's a middle state, used to remove the rule node in the fd_rule_list. ACTIVE: the rule is already added in hardware
For asynchronous way, when receive a new request to add or delete flow director rule by aRFS, update the rule list, then request to schedule the service task to finish the configuration.
For synchronous way, when receive a new request to add or delete flow director rule by ethtool or tc flower, configure hardware directly, then update the rule list if success.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 518 +++++++++++------- .../hisilicon/hns3/hns3pf/hclge_main.h | 10 + 2 files changed, 319 insertions(+), 209 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6f355df95ae5..1c59b7d7c4c2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -62,7 +62,7 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev); static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev); static bool hclge_get_hw_reset_stat(struct hnae3_handle *handle); static void hclge_rfs_filter_expire(struct hclge_dev *hdev); -static void hclge_clear_arfs_rules(struct hnae3_handle *handle); +static int hclge_clear_arfs_rules(struct hclge_dev *hdev); static enum hnae3_reset_type hclge_get_reset_level(struct hnae3_ae_dev *ae_dev, unsigned long *addr); static int hclge_set_default_loopback(struct hclge_dev *hdev); @@ -70,6 +70,7 @@ static int hclge_set_default_loopback(struct hclge_dev *hdev); static void hclge_sync_mac_table(struct hclge_dev *hdev); static void hclge_restore_hw_table(struct hclge_dev *hdev); static void hclge_sync_promisc_mode(struct hclge_dev *hdev); +static void hclge_sync_fd_table(struct hclge_dev *hdev);
static struct hnae3_ae_algo ae_algo;
@@ -4261,6 +4262,7 @@ static void hclge_periodic_service_task(struct hclge_dev *hdev) hclge_update_link_status(hdev); hclge_sync_mac_table(hdev); hclge_sync_promisc_mode(hdev); + hclge_sync_fd_table(hdev);
if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) { delta = jiffies - hdev->last_serv_processed; @@ -5162,6 +5164,150 @@ static void hclge_request_update_promisc_mode(struct hnae3_handle *handle) set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); }
+static void hclge_sync_fd_state(struct hclge_dev *hdev) +{ + if (hlist_empty(&hdev->fd_rule_list)) + hdev->fd_active_type = HCLGE_FD_RULE_NONE; +} + +static void hclge_fd_inc_rule_cnt(struct hclge_dev *hdev, u16 location) +{ + if (!test_bit(location, hdev->fd_bmap)) { + set_bit(location, hdev->fd_bmap); + hdev->hclge_fd_rule_num++; + } +} + +static void hclge_fd_dec_rule_cnt(struct hclge_dev *hdev, u16 location) +{ + if (test_bit(location, hdev->fd_bmap)) { + clear_bit(location, hdev->fd_bmap); + hdev->hclge_fd_rule_num--; + } +} + +static void hclge_fd_free_node(struct hclge_dev *hdev, + struct hclge_fd_rule *rule) +{ + hlist_del(&rule->rule_node); + kfree(rule); + hclge_sync_fd_state(hdev); +} + +static void hclge_update_fd_rule_node(struct hclge_dev *hdev, + struct hclge_fd_rule *old_rule, + struct hclge_fd_rule *new_rule, + enum HCLGE_FD_NODE_STATE state) +{ + switch (state) { + case HCLGE_FD_TO_ADD: + case HCLGE_FD_ACTIVE: + /* 1) if the new state is TO_ADD, just replace the old rule + * with the same location, no matter its state, because the + * new rule will be configured to the hardware. + * 2) if the new state is ACTIVE, it means the new rule + * has been configured to the hardware, so just replace + * the old rule node with the same location. + * 3) for it doesn't add a new node to the list, so it's + * unnecessary to update the rule number and fd_bmap. + */ + new_rule->rule_node.next = old_rule->rule_node.next; + new_rule->rule_node.pprev = old_rule->rule_node.pprev; + memcpy(old_rule, new_rule, sizeof(*old_rule)); + kfree(new_rule); + break; + case HCLGE_FD_DELETED: + hclge_fd_dec_rule_cnt(hdev, old_rule->location); + hclge_fd_free_node(hdev, old_rule); + break; + case HCLGE_FD_TO_DEL: + /* if new request is TO_DEL, and old rule is existent + * 1) the state of old rule is TO_DEL, we need do nothing, + * because we delete rule by location, other rule content + * is unncessary. + * 2) the state of old rule is ACTIVE, we need to change its + * state to TO_DEL, so the rule will be deleted when periodic + * task being scheduled. + * 3) the state of old rule is TO_ADD, it means the rule hasn't + * been added to hardware, so we just delete the rule node from + * fd_rule_list directly. + */ + if (old_rule->state == HCLGE_FD_TO_ADD) { + hclge_fd_dec_rule_cnt(hdev, old_rule->location); + hclge_fd_free_node(hdev, old_rule); + return; + } + old_rule->state = HCLGE_FD_TO_DEL; + break; + } +} + +static struct hclge_fd_rule *hclge_find_fd_rule(struct hlist_head *hlist, + u16 location, + struct hclge_fd_rule **parent) +{ + struct hclge_fd_rule *rule; + struct hlist_node *node; + + hlist_for_each_entry_safe(rule, node, hlist, rule_node) { + if (rule->location == location) + return rule; + else if (rule->location > location) + return NULL; + /* record the parent node, use to keep the nodes in fd_rule_list + * in ascend order. + */ + *parent = rule; + } + + return NULL; +} + +/* insert fd rule node in ascend order according to rule->location */ +static void hclge_fd_insert_rule_node(struct hlist_head *hlist, + struct hclge_fd_rule *rule, + struct hclge_fd_rule *parent) +{ + INIT_HLIST_NODE(&rule->rule_node); + + if (parent) + hlist_add_behind(&rule->rule_node, &parent->rule_node); + else + hlist_add_head(&rule->rule_node, hlist); +} + +static void hclge_update_fd_list(struct hclge_dev *hdev, + enum HCLGE_FD_NODE_STATE state, u16 location, + struct hclge_fd_rule *new_rule) +{ + struct hlist_head *hlist = &hdev->fd_rule_list; + struct hclge_fd_rule *fd_rule, *parent = NULL; + + fd_rule = hclge_find_fd_rule(hlist, location, &parent); + if (fd_rule) { + hclge_update_fd_rule_node(hdev, fd_rule, new_rule, state); + return; + } + + /* it's unlikely to fail here, because we have checked the rule + * exist before. + */ + if (unlikely(state == HCLGE_FD_TO_DEL || state == HCLGE_FD_DELETED)) { + dev_warn(&hdev->pdev->dev, + "failed to delete fd rule %u, it's inexistent\n", + location); + return; + } + + hclge_fd_insert_rule_node(hlist, new_rule, parent); + hclge_fd_inc_rule_cnt(hdev, new_rule->location); + + if (state == HCLGE_FD_TO_ADD) { + set_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state); + hclge_task_schedule(hdev, 0); + } +} + static int hclge_get_fd_mode(struct hclge_dev *hdev, u8 *fd_mode) { struct hclge_get_fd_mode_cmd *req; @@ -5847,74 +5993,6 @@ static int hclge_fd_check_spec(struct hclge_dev *hdev, return hclge_fd_check_ext_tuple(hdev, fs, unused_tuple); }
-static bool hclge_fd_rule_exist(struct hclge_dev *hdev, u16 location) -{ - struct hclge_fd_rule *rule = NULL; - struct hlist_node *node2; - - spin_lock_bh(&hdev->fd_rule_lock); - hlist_for_each_entry_safe(rule, node2, &hdev->fd_rule_list, rule_node) { - if (rule->location >= location) - break; - } - - spin_unlock_bh(&hdev->fd_rule_lock); - - return rule && rule->location == location; -} - -/* make sure being called after lock up with fd_rule_lock */ -static int hclge_fd_update_rule_list(struct hclge_dev *hdev, - struct hclge_fd_rule *new_rule, - u16 location, - bool is_add) -{ - struct hclge_fd_rule *rule = NULL, *parent = NULL; - struct hlist_node *node2; - - if (is_add && !new_rule) - return -EINVAL; - - hlist_for_each_entry_safe(rule, node2, - &hdev->fd_rule_list, rule_node) { - if (rule->location >= location) - break; - parent = rule; - } - - if (rule && rule->location == location) { - hlist_del(&rule->rule_node); - kfree(rule); - hdev->hclge_fd_rule_num--; - - if (!is_add) { - if (!hdev->hclge_fd_rule_num) - hdev->fd_active_type = HCLGE_FD_RULE_NONE; - clear_bit(location, hdev->fd_bmap); - - return 0; - } - } else if (!is_add) { - dev_err(&hdev->pdev->dev, - "delete fail, rule %u is inexistent\n", - location); - return -EINVAL; - } - - INIT_HLIST_NODE(&new_rule->rule_node); - - if (parent) - hlist_add_behind(&new_rule->rule_node, &parent->rule_node); - else - hlist_add_head(&new_rule->rule_node, &hdev->fd_rule_list); - - set_bit(location, hdev->fd_bmap); - hdev->hclge_fd_rule_num++; - hdev->fd_active_type = new_rule->rule_type; - - return 0; -} - static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev, struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule, u8 ip_proto) @@ -6088,33 +6166,48 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev, return 0; }
-/* make sure being called after lock up with fd_rule_lock */ static int hclge_fd_config_rule(struct hclge_dev *hdev, struct hclge_fd_rule *rule) { int ret;
- if (!rule) { + ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule); + if (ret) + return ret; + + return hclge_config_key(hdev, HCLGE_FD_STAGE_1, rule); +} + +static int hclge_add_fd_entry_common(struct hclge_dev *hdev, + struct hclge_fd_rule *rule) +{ + int ret; + + spin_lock_bh(&hdev->fd_rule_lock); + + if (hdev->fd_active_type != rule->rule_type && + (hdev->fd_active_type == HCLGE_FD_TC_FLOWER_ACTIVE || + hdev->fd_active_type == HCLGE_FD_EP_ACTIVE)) { dev_err(&hdev->pdev->dev, - "The flow director rule is NULL\n"); + "mode conflict(new type %d, active type %d), please delete existent rules first\n", + rule->rule_type, hdev->fd_active_type); + spin_unlock_bh(&hdev->fd_rule_lock); return -EINVAL; }
- /* it will never fail here, so needn't to check return value */ - hclge_fd_update_rule_list(hdev, rule, rule->location, true); - - ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule); + ret = hclge_clear_arfs_rules(hdev); if (ret) - goto clear_rule; + goto out;
- ret = hclge_config_key(hdev, HCLGE_FD_STAGE_1, rule); + ret = hclge_fd_config_rule(hdev, rule); if (ret) - goto clear_rule; + goto out;
- return 0; + hclge_update_fd_list(hdev, HCLGE_FD_ACTIVE, rule->location, rule); + hdev->fd_active_type = rule->rule_type;
-clear_rule: - hclge_fd_update_rule_list(hdev, rule, rule->location, false); +out: + spin_unlock_bh(&hdev->fd_rule_lock); return ret; }
@@ -6186,12 +6279,6 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, return -EOPNOTSUPP; }
- if (hclge_is_cls_flower_active(handle)) { - dev_err(&hdev->pdev->dev, - "please delete all exist cls flower rules first\n"); - return -EINVAL; - } - fs = (struct ethtool_rx_flow_spec *)&cmd->fs;
ret = hclge_fd_check_spec(hdev, fs, &unused); @@ -6221,15 +6308,9 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, rule->action = action; rule->rule_type = HCLGE_FD_EP_ACTIVE;
- /* to avoid rule conflict, when user configure rule by ethtool, - * we need to clear all arfs rules - */ - spin_lock_bh(&hdev->fd_rule_lock); - hclge_clear_arfs_rules(handle); - - ret = hclge_fd_config_rule(hdev, rule); - - spin_unlock_bh(&hdev->fd_rule_lock); + ret = hclge_add_fd_entry_common(hdev, rule); + if (ret) + kfree(rule);
return ret; } @@ -6250,32 +6331,30 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle, if (fs->location >= hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]) return -EINVAL;
- if (hclge_is_cls_flower_active(handle) || !hdev->hclge_fd_rule_num || - !hclge_fd_rule_exist(hdev, fs->location)) { + spin_lock_bh(&hdev->fd_rule_lock); + if (hdev->fd_active_type == HCLGE_FD_TC_FLOWER_ACTIVE || + !test_bit(fs->location, hdev->fd_bmap)) { dev_err(&hdev->pdev->dev, "Delete fail, rule %u is inexistent\n", fs->location); + spin_unlock_bh(&hdev->fd_rule_lock); return -ENOENT; }
ret = hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, fs->location, NULL, false); if (ret) - return ret; + goto out;
- spin_lock_bh(&hdev->fd_rule_lock); - ret = hclge_fd_update_rule_list(hdev, NULL, fs->location, false); + hclge_update_fd_list(hdev, HCLGE_FD_DELETED, fs->location, NULL);
+out: spin_unlock_bh(&hdev->fd_rule_lock); - return ret; }
-/* make sure being called after lock up with fd_rule_lock */ -static void hclge_del_all_fd_entries(struct hnae3_handle *handle, - bool clear_list) +static void hclge_clear_fd_rules_in_list(struct hclge_dev *hdev, + bool clear_list) { - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; struct hclge_fd_rule *rule; struct hlist_node *node; u16 location; @@ -6283,6 +6362,8 @@ static void hclge_del_all_fd_entries(struct hnae3_handle *handle, if (!hnae3_dev_fd_supported(hdev)) return;
+ spin_lock_bh(&hdev->fd_rule_lock); + for_each_set_bit(location, hdev->fd_bmap, hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]) hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, location, @@ -6299,6 +6380,17 @@ static void hclge_del_all_fd_entries(struct hnae3_handle *handle, bitmap_zero(hdev->fd_bmap, hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]); } + + spin_unlock_bh(&hdev->fd_rule_lock); +} + +static void hclge_del_all_fd_entries(struct hnae3_handle *handle, + bool clear_list) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + + hclge_clear_fd_rules_in_list(hdev, clear_list); }
static int hclge_restore_fd_entries(struct hnae3_handle *handle) @@ -6307,7 +6399,6 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle) struct hclge_dev *hdev = vport->back; struct hclge_fd_rule *rule; struct hlist_node *node; - int ret;
/* Return ok here, because reset error handling will check this * return value. If error is returned here, the reset process will @@ -6322,25 +6413,11 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
spin_lock_bh(&hdev->fd_rule_lock); hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) { - ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule); - if (!ret) - ret = hclge_config_key(hdev, HCLGE_FD_STAGE_1, rule); - - if (ret) { - dev_warn(&hdev->pdev->dev, - "Restore rule %u failed, remove it\n", - rule->location); - clear_bit(rule->location, hdev->fd_bmap); - hlist_del(&rule->rule_node); - kfree(rule); - hdev->hclge_fd_rule_num--; - } + if (rule->state == HCLGE_FD_ACTIVE) + rule->state = HCLGE_FD_TO_ADD; } - - if (hdev->hclge_fd_rule_num) - hdev->fd_active_type = HCLGE_FD_EP_ACTIVE; - spin_unlock_bh(&hdev->fd_rule_lock); + set_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state);
return 0; } @@ -6609,6 +6686,9 @@ static int hclge_get_all_rules(struct hnae3_handle *handle, return -EMSGSIZE; }
+ if (rule->state == HCLGE_FD_TO_DEL) + continue; + rule_locs[cnt] = rule->location; cnt++; } @@ -6690,9 +6770,7 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id, struct hclge_fd_rule_tuples new_tuples = {}; struct hclge_dev *hdev = vport->back; struct hclge_fd_rule *rule; - u16 tmp_queue_id; u16 bit_id; - int ret;
if (!hnae3_dev_fd_supported(hdev)) return -EOPNOTSUPP; @@ -6728,34 +6806,20 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id, return -ENOMEM; }
- set_bit(bit_id, hdev->fd_bmap); rule->location = bit_id; rule->arfs.flow_id = flow_id; rule->queue_id = queue_id; hclge_fd_build_arfs_rule(&new_tuples, rule); - ret = hclge_fd_config_rule(hdev, rule); - - spin_unlock_bh(&hdev->fd_rule_lock); - - if (ret) - return ret; - - return rule->location; + hclge_update_fd_list(hdev, HCLGE_FD_TO_ADD, rule->location, + rule); + hdev->fd_active_type = HCLGE_FD_ARFS_ACTIVE; + } else if (rule->queue_id != queue_id) { + rule->queue_id = queue_id; + rule->state = HCLGE_FD_TO_ADD; + set_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state); + hclge_task_schedule(hdev, 0); } - spin_unlock_bh(&hdev->fd_rule_lock); - - if (rule->queue_id == queue_id) - return rule->location; - - tmp_queue_id = rule->queue_id; - rule->queue_id = queue_id; - ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule); - if (ret) { - rule->queue_id = tmp_queue_id; - return ret; - } - return rule->location; }
@@ -6765,7 +6829,6 @@ static void hclge_rfs_filter_expire(struct hclge_dev *hdev) struct hnae3_handle *handle = &hdev->vport[0].nic; struct hclge_fd_rule *rule; struct hlist_node *node; - HLIST_HEAD(del_list);
spin_lock_bh(&hdev->fd_rule_lock); if (hdev->fd_active_type != HCLGE_FD_ARFS_ACTIVE) { @@ -6773,33 +6836,50 @@ static void hclge_rfs_filter_expire(struct hclge_dev *hdev) return; } hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) { + if (rule->state != HCLGE_FD_ACTIVE) + continue; if (rps_may_expire_flow(handle->netdev, rule->queue_id, rule->arfs.flow_id, rule->location)) { - hlist_del_init(&rule->rule_node); - hlist_add_head(&rule->rule_node, &del_list); - hdev->hclge_fd_rule_num--; - clear_bit(rule->location, hdev->fd_bmap); + rule->state = HCLGE_FD_TO_DEL; + set_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state); } } spin_unlock_bh(&hdev->fd_rule_lock); - - hlist_for_each_entry_safe(rule, node, &del_list, rule_node) { - hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, - rule->location, NULL, false); - kfree(rule); - } #endif }
/* make sure being called after lock up with fd_rule_lock */ -static void hclge_clear_arfs_rules(struct hnae3_handle *handle) +static int hclge_clear_arfs_rules(struct hclge_dev *hdev) { #ifdef CONFIG_RFS_ACCEL - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; + struct hclge_fd_rule *rule; + struct hlist_node *node; + int ret; + + if (hdev->fd_active_type != HCLGE_FD_ARFS_ACTIVE) + return 0; + + hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) { + switch (rule->state) { + case HCLGE_FD_TO_DEL: + case HCLGE_FD_ACTIVE: + ret = hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, + rule->location, NULL, false); + if (ret) + return ret; + fallthrough; + case HCLGE_FD_TO_ADD: + hclge_fd_dec_rule_cnt(hdev, rule->location); + hlist_del(&rule->rule_node); + kfree(rule); + break; + default: + break; + } + } + hclge_sync_fd_state(hdev);
- if (hdev->fd_active_type == HCLGE_FD_ARFS_ACTIVE) - hclge_del_all_fd_entries(handle, true); + return 0; #endif }
@@ -6982,12 +7062,6 @@ static int hclge_add_cls_flower(struct hnae3_handle *handle, struct hclge_fd_rule *rule; int ret;
- if (hdev->fd_active_type == HCLGE_FD_EP_ACTIVE) { - dev_err(&hdev->pdev->dev, - "please remove all exist fd rules via ethtool first\n"); - return -EINVAL; - } - ret = hclge_check_cls_flower(hdev, cls_flower, tc); if (ret) { dev_err(&hdev->pdev->dev, @@ -7000,8 +7074,10 @@ static int hclge_add_cls_flower(struct hnae3_handle *handle, return -ENOMEM;
ret = hclge_parse_cls_flower(hdev, cls_flower, rule); - if (ret) - goto err; + if (ret) { + kfree(rule); + return ret; + }
rule->action = HCLGE_FD_ACTION_SELECT_TC; rule->cls_flower.tc = tc; @@ -7010,22 +7086,10 @@ static int hclge_add_cls_flower(struct hnae3_handle *handle, rule->cls_flower.cookie = cls_flower->cookie; rule->rule_type = HCLGE_FD_TC_FLOWER_ACTIVE;
- spin_lock_bh(&hdev->fd_rule_lock); - hclge_clear_arfs_rules(handle); - - ret = hclge_fd_config_rule(hdev, rule); - - spin_unlock_bh(&hdev->fd_rule_lock); - - if (ret) { - dev_err(&hdev->pdev->dev, - "failed to add cls flower rule, ret = %d\n", ret); - goto err; - } + ret = hclge_add_fd_entry_common(hdev, rule); + if (ret) + kfree(rule);
- return 0; -err: - kfree(rule); return ret; }
@@ -7062,25 +7126,64 @@ static int hclge_del_cls_flower(struct hnae3_handle *handle, ret = hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, rule->location, NULL, false); if (ret) { - dev_err(&hdev->pdev->dev, - "failed to delete cls flower rule %u, ret = %d\n", - rule->location, ret); spin_unlock_bh(&hdev->fd_rule_lock); return ret; }
- ret = hclge_fd_update_rule_list(hdev, NULL, rule->location, false); - if (ret) { - dev_err(&hdev->pdev->dev, - "failed to delete cls flower rule %u in list, ret = %d\n", - rule->location, ret); - spin_unlock_bh(&hdev->fd_rule_lock); - return ret; + hclge_update_fd_list(hdev, HCLGE_FD_DELETED, rule->location, NULL); + spin_unlock_bh(&hdev->fd_rule_lock); + + return 0; +} + +static void hclge_sync_fd_list(struct hclge_dev *hdev, struct hlist_head *hlist) +{ + struct hclge_fd_rule *rule; + struct hlist_node *node; + int ret = 0; + + if (!test_and_clear_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state)) + return; + + spin_lock_bh(&hdev->fd_rule_lock); + + hlist_for_each_entry_safe(rule, node, hlist, rule_node) { + switch (rule->state) { + case HCLGE_FD_TO_ADD: + ret = hclge_fd_config_rule(hdev, rule); + if (ret) + goto out; + rule->state = HCLGE_FD_ACTIVE; + break; + case HCLGE_FD_TO_DEL: + ret = hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, + rule->location, NULL, false); + if (ret) + goto out; + hclge_fd_dec_rule_cnt(hdev, rule->location); + hclge_fd_free_node(hdev, rule); + break; + default: + break; + } }
+out: + if (ret) + set_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state); + spin_unlock_bh(&hdev->fd_rule_lock); +}
- return 0; +static void hclge_sync_fd_table(struct hclge_dev *hdev) +{ + if (test_and_clear_bit(HCLGE_STATE_FD_CLEAR_ALL, &hdev->state)) { + bool clear_list = hdev->fd_active_type == HCLGE_FD_ARFS_ACTIVE; + + hclge_clear_fd_rules_in_list(hdev, clear_list); + } + + hclge_sync_fd_list(hdev, &hdev->fd_rule_list); }
static bool hclge_get_hw_reset_stat(struct hnae3_handle *handle) @@ -7120,18 +7223,15 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - bool clear;
hdev->fd_en = enable; - clear = hdev->fd_active_type == HCLGE_FD_ARFS_ACTIVE;
- if (!enable) { - spin_lock_bh(&hdev->fd_rule_lock); - hclge_del_all_fd_entries(handle, clear); - spin_unlock_bh(&hdev->fd_rule_lock); - } else { + if (!enable) + set_bit(HCLGE_STATE_FD_CLEAR_ALL, &hdev->state); + else hclge_restore_fd_entries(handle); - } + + hclge_task_schedule(hdev, 0); }
static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) @@ -7602,7 +7702,7 @@ static void hclge_ae_stop(struct hnae3_handle *handle)
set_bit(HCLGE_STATE_DOWN, &hdev->state); spin_lock_bh(&hdev->fd_rule_lock); - hclge_clear_arfs_rules(handle); + hclge_clear_arfs_rules(hdev); spin_unlock_bh(&hdev->fd_rule_lock);
/* If it is not PF reset, the firmware will disable the MAC, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6fe745538b30..ccc79d9b2e2b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -223,6 +223,8 @@ enum HCLGE_DEV_STATE { HCLGE_STATE_LINK_UPDATING, HCLGE_STATE_PROMISC_CHANGED, HCLGE_STATE_RST_FAIL, + HCLGE_STATE_FD_TBL_CHANGED, + HCLGE_STATE_FD_CLEAR_ALL, HCLGE_STATE_MAX };
@@ -592,6 +594,13 @@ enum HCLGE_FD_ACTION { HCLGE_FD_ACTION_SELECT_TC, };
+enum HCLGE_FD_NODE_STATE { + HCLGE_FD_TO_ADD, + HCLGE_FD_TO_DEL, + HCLGE_FD_ACTIVE, + HCLGE_FD_DELETED, +}; + struct hclge_fd_key_cfg { u8 key_sel; u8 inner_sipv6_word_en; @@ -647,6 +656,7 @@ struct hclge_fd_rule { u16 vf_id; u16 location; enum HCLGE_FD_ACTIVE_RULE_TYPE rule_type; + enum HCLGE_FD_NODE_STATE state; u8 action; };
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit f07203b0180f62791371cb50fb1afacd826250fc category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
For only PF driver can configure flow director rule, it's better to call hclge_del_all_fd_entries() directly in hclge layer, rather than call hns3_del_all_fd_entries() in hns3 layer. Then the ae_algo->ops.del_all_fd_entries can be removed.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 -- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 10 ---------- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 +++------- 3 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 227b200cc6c5..0d1a28b81991 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -611,8 +611,6 @@ struct hnae3_ae_ops { struct ethtool_rxnfc *cmd); int (*del_fd_entry)(struct hnae3_handle *handle, struct ethtool_rxnfc *cmd); - void (*del_all_fd_entries)(struct hnae3_handle *handle, - bool clear_list); int (*get_fd_rule_cnt)(struct hnae3_handle *handle, struct ethtool_rxnfc *cmd); int (*get_fd_rule_info)(struct hnae3_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index aa9870b255c6..c4a045987c2f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4174,14 +4174,6 @@ static void hns3_uninit_phy(struct net_device *netdev) h->ae_algo->ops->mac_disconnect_phy(h); }
-static void hns3_del_all_fd_rules(struct net_device *netdev, bool clear_list) -{ - struct hnae3_handle *h = hns3_get_handle(netdev); - - if (h->ae_algo->ops->del_all_fd_entries) - h->ae_algo->ops->del_all_fd_entries(h, clear_list); -} - static int hns3_client_start(struct hnae3_handle *handle) { if (!handle->ae_algo->ops->client_start) @@ -4368,8 +4360,6 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
hns3_nic_uninit_irq(priv);
- hns3_del_all_fd_rules(netdev, true); - hns3_clear_all_ring(handle, true);
hns3_nic_uninit_vector_data(priv); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 1c59b7d7c4c2..c84e17d25970 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6384,13 +6384,9 @@ static void hclge_clear_fd_rules_in_list(struct hclge_dev *hdev, spin_unlock_bh(&hdev->fd_rule_lock); }
-static void hclge_del_all_fd_entries(struct hnae3_handle *handle, - bool clear_list) +static void hclge_del_all_fd_entries(struct hclge_dev *hdev) { - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - - hclge_clear_fd_rules_in_list(hdev, clear_list); + hclge_clear_fd_rules_in_list(hdev, true); }
static int hclge_restore_fd_entries(struct hnae3_handle *handle) @@ -11427,6 +11423,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_misc_affinity_teardown(hdev); hclge_state_uninit(hdev); hclge_uninit_mac_table(hdev); + hclge_del_all_fd_entries(hdev);
if (mac->phydev) mdiobus_unregister(mac->mdio_bus); @@ -12263,7 +12260,6 @@ static const struct hnae3_ae_ops hclge_ops = { .get_link_mode = hclge_get_link_mode, .add_fd_entry = hclge_add_fd_entry, .del_fd_entry = hclge_del_fd_entry, - .del_all_fd_entries = hclge_del_all_fd_entries, .get_fd_rule_cnt = hclge_get_fd_rule_cnt, .get_fd_rule_info = hclge_get_fd_rule_info, .get_fd_all_rules = hclge_get_all_rules,
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 67b0e1428e2f592c0fc2c7f682a5a049158782b8 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
For DEVICE_VERSION_V3, the hardware supports to match specified data in the specified offset of packet payload. Each layer can have one offset, and can't be masked when configure flow director rule by ethtool command. The layer is selected based on the flow-type, ether for L2, ip4/ipv6 for L3, and tcp4/tcp6/udp4/udp6 for L4. For example, tcp4/tcp6/udp4/udp6 rules share the same user-def offset, but each rule can have its own user-def value.
For the user-def field of ethtool -N/U command is 64 bits long. The bit 0~15 is used for user-def value, and bit 32~47 for user-def offset in HNS3 driver.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 14 + .../hisilicon/hns3/hns3pf/hclge_main.c | 323 +++++++++++++++++- .../hisilicon/hns3/hns3pf/hclge_main.h | 36 ++ 3 files changed, 359 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 804f4c8360cf..565c5aa54f88 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -243,6 +243,7 @@ enum hclge_opcode_type { HCLGE_OPC_FD_KEY_CONFIG = 0x1202, HCLGE_OPC_FD_TCAM_OP = 0x1203, HCLGE_OPC_FD_AD_OP = 0x1204, + HCLGE_OPC_FD_USER_DEF_OP = 0x1207,
/* MDIO command */ HCLGE_OPC_MDIO_CONFIG = 0x1900, @@ -1082,6 +1083,19 @@ struct hclge_fd_ad_config_cmd { u8 rsv2[8]; };
+#define HCLGE_FD_USER_DEF_OFT_S 0 +#define HCLGE_FD_USER_DEF_OFT_M GENMASK(14, 0) +#define HCLGE_FD_USER_DEF_EN_B 15 +struct hclge_fd_user_def_cfg_cmd { + __le16 ol2_cfg; + __le16 l2_cfg; + __le16 ol3_cfg; + __le16 l3_cfg; + __le16 ol4_cfg; + __le16 l4_cfg; + u8 rsv[12]; +}; + struct hclge_get_m7_bd_cmd { __le32 bd_num; u8 rsv[20]; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c84e17d25970..aaee51ce4039 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -414,7 +414,9 @@ static const struct key_info tuple_key_info[] = { { INNER_ETH_TYPE, 16, KEY_OPT_LE16, offsetof(struct hclge_fd_rule, tuples.ether_proto), offsetof(struct hclge_fd_rule, tuples_mask.ether_proto) }, - { INNER_L2_RSV, 16, KEY_OPT_LE16, -1, -1 }, + { INNER_L2_RSV, 16, KEY_OPT_LE16, + offsetof(struct hclge_fd_rule, tuples.l2_user_def), + offsetof(struct hclge_fd_rule, tuples_mask.l2_user_def) }, { INNER_IP_TOS, 8, KEY_OPT_U8, offsetof(struct hclge_fd_rule, tuples.ip_tos), offsetof(struct hclge_fd_rule, tuples_mask.ip_tos) }, @@ -427,14 +429,18 @@ static const struct key_info tuple_key_info[] = { { INNER_DST_IP, 32, KEY_OPT_IP, offsetof(struct hclge_fd_rule, tuples.dst_ip), offsetof(struct hclge_fd_rule, tuples_mask.dst_ip) }, - { INNER_L3_RSV, 16, KEY_OPT_LE16, -1, -1 }, + { INNER_L3_RSV, 16, KEY_OPT_LE16, + offsetof(struct hclge_fd_rule, tuples.l3_user_def), + offsetof(struct hclge_fd_rule, tuples_mask.l3_user_def) }, { INNER_SRC_PORT, 16, KEY_OPT_LE16, offsetof(struct hclge_fd_rule, tuples.src_port), offsetof(struct hclge_fd_rule, tuples_mask.src_port) }, { INNER_DST_PORT, 16, KEY_OPT_LE16, offsetof(struct hclge_fd_rule, tuples.dst_port), offsetof(struct hclge_fd_rule, tuples_mask.dst_port) }, - { INNER_L4_RSV, 32, KEY_OPT_LE32, -1, -1 }, + { INNER_L4_RSV, 32, KEY_OPT_LE32, + offsetof(struct hclge_fd_rule, tuples.l4_user_def), + offsetof(struct hclge_fd_rule, tuples_mask.l4_user_def) }, };
static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) @@ -5276,6 +5282,133 @@ static void hclge_fd_insert_rule_node(struct hlist_head *hlist, hlist_add_head(&rule->rule_node, hlist); }
+static int hclge_fd_set_user_def_cmd(struct hclge_dev *hdev, + struct hclge_fd_user_def_cfg *cfg) +{ + struct hclge_fd_user_def_cfg_cmd *req; + struct hclge_desc desc; + u16 data = 0; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_FD_USER_DEF_OP, false); + + req = (struct hclge_fd_user_def_cfg_cmd *)desc.data; + + hnae3_set_bit(data, HCLGE_FD_USER_DEF_EN_B, cfg[0].ref_cnt > 0); + hnae3_set_field(data, HCLGE_FD_USER_DEF_OFT_M, + HCLGE_FD_USER_DEF_OFT_S, cfg[0].offset); + req->ol2_cfg = cpu_to_le16(data); + + data = 0; + hnae3_set_bit(data, HCLGE_FD_USER_DEF_EN_B, cfg[1].ref_cnt > 0); + hnae3_set_field(data, HCLGE_FD_USER_DEF_OFT_M, + HCLGE_FD_USER_DEF_OFT_S, cfg[1].offset); + req->ol3_cfg = cpu_to_le16(data); + + data = 0; + hnae3_set_bit(data, HCLGE_FD_USER_DEF_EN_B, cfg[2].ref_cnt > 0); + hnae3_set_field(data, HCLGE_FD_USER_DEF_OFT_M, + HCLGE_FD_USER_DEF_OFT_S, cfg[2].offset); + req->ol4_cfg = cpu_to_le16(data); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to set fd user def data, ret= %d\n", ret); + return ret; +} + +static void hclge_sync_fd_user_def_cfg(struct hclge_dev *hdev, bool locked) +{ + int ret; + + if (!test_and_clear_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state)) + return; + + if (!locked) + spin_lock_bh(&hdev->fd_rule_lock); + + ret = hclge_fd_set_user_def_cmd(hdev, hdev->fd_cfg.user_def_cfg); + if (ret) + set_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state); + + if (!locked) + spin_unlock_bh(&hdev->fd_rule_lock); +} + +static int hclge_fd_check_user_def_refcnt(struct hclge_dev *hdev, + struct hclge_fd_rule *rule) +{ + struct hlist_head *hlist = &hdev->fd_rule_list; + struct hclge_fd_rule *fd_rule, *parent = NULL; + struct hclge_fd_user_def_info *info, *old_info; + struct hclge_fd_user_def_cfg *cfg; + + if (!rule || rule->rule_type != HCLGE_FD_EP_ACTIVE || + rule->ep.user_def.layer == HCLGE_FD_USER_DEF_NONE) + return 0; + + /* for valid layer is start from 1, so need minus 1 to get the cfg */ + cfg = &hdev->fd_cfg.user_def_cfg[rule->ep.user_def.layer - 1]; + info = &rule->ep.user_def; + + if (!cfg->ref_cnt || cfg->offset == info->offset) + return 0; + + if (cfg->ref_cnt > 1) + goto error; + + fd_rule = hclge_find_fd_rule(hlist, rule->location, &parent); + if (fd_rule) { + old_info = &fd_rule->ep.user_def; + if (info->layer == old_info->layer) + return 0; + } + +error: + dev_err(&hdev->pdev->dev, + "No available offset for layer%d fd rule, each layer only support one user def offset.\n", + info->layer + 1); + return -ENOSPC; +} + +static void hclge_fd_inc_user_def_refcnt(struct hclge_dev *hdev, + struct hclge_fd_rule *rule) +{ + struct hclge_fd_user_def_cfg *cfg; + + if (!rule || rule->rule_type != HCLGE_FD_EP_ACTIVE || + rule->ep.user_def.layer == HCLGE_FD_USER_DEF_NONE) + return; + + cfg = &hdev->fd_cfg.user_def_cfg[rule->ep.user_def.layer - 1]; + if (!cfg->ref_cnt) { + cfg->offset = rule->ep.user_def.offset; + set_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state); + } + cfg->ref_cnt++; +} + +static void hclge_fd_dec_user_def_refcnt(struct hclge_dev *hdev, + struct hclge_fd_rule *rule) +{ + struct hclge_fd_user_def_cfg *cfg; + + if (!rule || rule->rule_type != HCLGE_FD_EP_ACTIVE || + rule->ep.user_def.layer == HCLGE_FD_USER_DEF_NONE) + return; + + cfg = &hdev->fd_cfg.user_def_cfg[rule->ep.user_def.layer - 1]; + if (!cfg->ref_cnt) + return; + + cfg->ref_cnt--; + if (!cfg->ref_cnt) { + cfg->offset = 0; + set_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state); + } +} + static void hclge_update_fd_list(struct hclge_dev *hdev, enum HCLGE_FD_NODE_STATE state, u16 location, struct hclge_fd_rule *new_rule) @@ -5285,6 +5418,11 @@ static void hclge_update_fd_list(struct hclge_dev *hdev,
fd_rule = hclge_find_fd_rule(hlist, location, &parent); if (fd_rule) { + hclge_fd_dec_user_def_refcnt(hdev, fd_rule); + if (state == HCLGE_FD_ACTIVE) + hclge_fd_inc_user_def_refcnt(hdev, new_rule); + hclge_sync_fd_user_def_cfg(hdev, true); + hclge_update_fd_rule_node(hdev, fd_rule, new_rule, state); return; } @@ -5299,6 +5437,9 @@ static void hclge_update_fd_list(struct hclge_dev *hdev, return; }
+ hclge_fd_inc_user_def_refcnt(hdev, new_rule); + hclge_sync_fd_user_def_cfg(hdev, true); + hclge_fd_insert_rule_node(hlist, new_rule, parent); hclge_fd_inc_rule_cnt(hdev, new_rule->location);
@@ -5386,6 +5527,17 @@ static int hclge_set_fd_key_config(struct hclge_dev *hdev, return ret; }
+static void hclge_fd_disable_user_def(struct hclge_dev *hdev) +{ + struct hclge_fd_user_def_cfg *cfg = hdev->fd_cfg.user_def_cfg; + + spin_lock_bh(&hdev->fd_rule_lock); + memset(cfg, 0, sizeof(hdev->fd_cfg.user_def_cfg)); + spin_unlock_bh(&hdev->fd_rule_lock); + + hclge_fd_set_user_def_cmd(hdev, cfg); +} + static int hclge_init_fd_config(struct hclge_dev *hdev) { #define LOW_2_WORDS 0x03 @@ -5426,9 +5578,12 @@ static int hclge_init_fd_config(struct hclge_dev *hdev) BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT);
/* If use max 400bit key, we can support tuples for ether type */ - if (hdev->fd_cfg.fd_mode == HCLGE_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1) + if (hdev->fd_cfg.fd_mode == HCLGE_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1) { key_cfg->tuple_active |= BIT(INNER_DST_MAC) | BIT(INNER_SRC_MAC); + if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) + key_cfg->tuple_active |= HCLGE_FD_TUPLE_USER_DEF_TUPLES; + }
/* roce_type is used to filter roce frames * dst_vport is used to specify the rule @@ -5922,9 +6077,98 @@ static int hclge_fd_check_ext_tuple(struct hclge_dev *hdev, return 0; }
+static int hclge_fd_get_user_def_layer(u32 flow_type, u32 *unused_tuple, + struct hclge_fd_user_def_info *info) +{ + switch (flow_type) { + case ETHER_FLOW: + info->layer = HCLGE_FD_USER_DEF_L2; + *unused_tuple &= ~BIT(INNER_L2_RSV); + break; + case IP_USER_FLOW: + case IPV6_USER_FLOW: + info->layer = HCLGE_FD_USER_DEF_L3; + *unused_tuple &= ~BIT(INNER_L3_RSV); + break; + case TCP_V4_FLOW: + case UDP_V4_FLOW: + case TCP_V6_FLOW: + case UDP_V6_FLOW: + info->layer = HCLGE_FD_USER_DEF_L4; + *unused_tuple &= ~BIT(INNER_L4_RSV); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static bool hclge_fd_is_user_def_all_masked(struct ethtool_rx_flow_spec *fs) +{ + return be32_to_cpu(fs->m_ext.data[1] | fs->m_ext.data[0]) == 0; +} + +static int hclge_fd_parse_user_def_field(struct hclge_dev *hdev, + struct ethtool_rx_flow_spec *fs, + u32 *unused_tuple, + struct hclge_fd_user_def_info *info) +{ + u32 tuple_active = hdev->fd_cfg.key_cfg[HCLGE_FD_STAGE_1].tuple_active; + u32 flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT); + u16 data, offset, data_mask, offset_mask; + int ret; + + info->layer = HCLGE_FD_USER_DEF_NONE; + *unused_tuple |= HCLGE_FD_TUPLE_USER_DEF_TUPLES; + + if (!(fs->flow_type & FLOW_EXT) || hclge_fd_is_user_def_all_masked(fs)) + return 0; + + /* user-def data from ethtool is 64 bit value, the bit0~15 is used + * for data, and bit32~47 is used for offset. + */ + data = be32_to_cpu(fs->h_ext.data[1]) & HCLGE_FD_USER_DEF_DATA; + data_mask = be32_to_cpu(fs->m_ext.data[1]) & HCLGE_FD_USER_DEF_DATA; + offset = be32_to_cpu(fs->h_ext.data[0]) & HCLGE_FD_USER_DEF_OFFSET; + offset_mask = be32_to_cpu(fs->m_ext.data[0]) & HCLGE_FD_USER_DEF_OFFSET; + + if (!(tuple_active & HCLGE_FD_TUPLE_USER_DEF_TUPLES)) { + dev_err(&hdev->pdev->dev, "user-def bytes are not supported\n"); + return -EOPNOTSUPP; + } + + if (offset > HCLGE_FD_MAX_USER_DEF_OFFSET) { + dev_err(&hdev->pdev->dev, + "user-def offset[%u] should be no more than %u\n", + offset, HCLGE_FD_MAX_USER_DEF_OFFSET); + return -EINVAL; + } + + if (offset_mask != HCLGE_FD_USER_DEF_OFFSET_UNMASK) { + dev_err(&hdev->pdev->dev, "user-def offset can't be masked\n"); + return -EINVAL; + } + + ret = hclge_fd_get_user_def_layer(flow_type, unused_tuple, info); + if (ret) { + dev_err(&hdev->pdev->dev, + "unsupported flow type for user-def bytes, ret = %d\n", + ret); + return ret; + } + + info->data = data; + info->data_mask = data_mask; + info->offset = offset; + + return 0; +} + static int hclge_fd_check_spec(struct hclge_dev *hdev, struct ethtool_rx_flow_spec *fs, - u32 *unused_tuple) + u32 *unused_tuple, + struct hclge_fd_user_def_info *info) { u32 flow_type; int ret; @@ -5937,11 +6181,9 @@ static int hclge_fd_check_spec(struct hclge_dev *hdev, return -EINVAL; }
- if ((fs->flow_type & FLOW_EXT) && - (fs->h_ext.data[0] != 0 || fs->h_ext.data[1] != 0)) { - dev_err(&hdev->pdev->dev, "user-def bytes are not supported\n"); - return -EOPNOTSUPP; - } + ret = hclge_fd_parse_user_def_field(hdev, fs, unused_tuple, info); + if (ret) + return ret;
flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT); switch (flow_type) { @@ -6115,9 +6357,33 @@ static void hclge_fd_get_ether_tuple(struct hclge_dev *hdev, rule->tuples_mask.ether_proto = be16_to_cpu(fs->m_u.ether_spec.h_proto); }
+static void hclge_fd_get_user_def_tuple(struct hclge_fd_user_def_info *info, + struct hclge_fd_rule *rule) +{ + switch (info->layer) { + case HCLGE_FD_USER_DEF_L2: + rule->tuples.l2_user_def = info->data; + rule->tuples_mask.l2_user_def = info->data_mask; + break; + case HCLGE_FD_USER_DEF_L3: + rule->tuples.l3_user_def = info->data; + rule->tuples_mask.l3_user_def = info->data_mask; + break; + case HCLGE_FD_USER_DEF_L4: + rule->tuples.l4_user_def = (u32)info->data << 16; + rule->tuples_mask.l4_user_def = (u32)info->data_mask << 16; + break; + default: + break; + } + + rule->ep.user_def = *info; +} + static int hclge_fd_get_tuple(struct hclge_dev *hdev, struct ethtool_rx_flow_spec *fs, - struct hclge_fd_rule *rule) + struct hclge_fd_rule *rule, + struct hclge_fd_user_def_info *info) { u32 flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT);
@@ -6156,6 +6422,7 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev, if (fs->flow_type & FLOW_EXT) { rule->tuples.vlan_tag1 = be16_to_cpu(fs->h_ext.vlan_tci); rule->tuples_mask.vlan_tag1 = be16_to_cpu(fs->m_ext.vlan_tci); + hclge_fd_get_user_def_tuple(info, rule); }
if (fs->flow_type & FLOW_MAC_EXT) { @@ -6195,6 +6462,10 @@ static int hclge_add_fd_entry_common(struct hclge_dev *hdev, return -EINVAL; }
+ ret = hclge_fd_check_user_def_refcnt(hdev, rule); + if (ret) + goto out; + ret = hclge_clear_arfs_rules(hdev); if (ret) goto out; @@ -6260,6 +6531,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + struct hclge_fd_user_def_info info; u16 dst_vport_id = 0, q_index = 0; struct ethtool_rx_flow_spec *fs; struct hclge_fd_rule *rule; @@ -6281,7 +6553,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
fs = (struct ethtool_rx_flow_spec *)&cmd->fs;
- ret = hclge_fd_check_spec(hdev, fs, &unused); + ret = hclge_fd_check_spec(hdev, fs, &unused, &info); if (ret) return ret;
@@ -6294,7 +6566,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, if (!rule) return -ENOMEM;
- ret = hclge_fd_get_tuple(hdev, fs, rule); + ret = hclge_fd_get_tuple(hdev, fs, rule, &info); if (ret) { kfree(rule); return ret; @@ -6387,6 +6659,7 @@ static void hclge_clear_fd_rules_in_list(struct hclge_dev *hdev, static void hclge_del_all_fd_entries(struct hclge_dev *hdev) { hclge_clear_fd_rules_in_list(hdev, true); + hclge_fd_disable_user_def(hdev); }
static int hclge_restore_fd_entries(struct hnae3_handle *handle) @@ -6563,6 +6836,24 @@ static void hclge_fd_get_ether_info(struct hclge_fd_rule *rule, 0 : cpu_to_be16(rule->tuples_mask.ether_proto); }
+static void hclge_fd_get_user_def_info(struct ethtool_rx_flow_spec *fs, + struct hclge_fd_rule *rule) +{ + if ((rule->unused_tuple & HCLGE_FD_TUPLE_USER_DEF_TUPLES) == + HCLGE_FD_TUPLE_USER_DEF_TUPLES) { + fs->h_ext.data[0] = 0; + fs->h_ext.data[1] = 0; + fs->m_ext.data[0] = 0; + fs->m_ext.data[1] = 0; + } else { + fs->h_ext.data[0] = cpu_to_be32(rule->ep.user_def.offset); + fs->h_ext.data[1] = cpu_to_be32(rule->ep.user_def.data); + fs->m_ext.data[0] = + cpu_to_be32(HCLGE_FD_USER_DEF_OFFSET_UNMASK); + fs->m_ext.data[1] = cpu_to_be32(rule->ep.user_def.data_mask); + } +} + static void hclge_fd_get_ext_info(struct ethtool_rx_flow_spec *fs, struct hclge_fd_rule *rule) { @@ -6571,6 +6862,8 @@ static void hclge_fd_get_ext_info(struct ethtool_rx_flow_spec *fs, fs->m_ext.vlan_tci = rule->unused_tuple & BIT(INNER_VLAN_TAG_FST) ? 0 : cpu_to_be16(rule->tuples_mask.vlan_tag1); + + hclge_fd_get_user_def_info(fs, rule); }
if (fs->flow_type & FLOW_MAC_EXT) { @@ -7179,6 +7472,8 @@ static void hclge_sync_fd_table(struct hclge_dev *hdev) hclge_clear_fd_rules_in_list(hdev, clear_list); }
+ hclge_sync_fd_user_def_cfg(hdev, false); + hclge_sync_fd_list(hdev, &hdev->fd_rule_list); }
@@ -9734,7 +10029,7 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev) hclge_restore_mac_table_common(vport); hclge_restore_vport_vlan_table(vport); set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); - + set_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state); hclge_restore_fd_entries(handle); }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index ccc79d9b2e2b..97e77e2f7539 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -225,6 +225,7 @@ enum HCLGE_DEV_STATE { HCLGE_STATE_RST_FAIL, HCLGE_STATE_FD_TBL_CHANGED, HCLGE_STATE_FD_CLEAR_ALL, + HCLGE_STATE_FD_USER_DEF_CHANGED, HCLGE_STATE_MAX };
@@ -538,6 +539,9 @@ enum HCLGE_FD_TUPLE { MAX_TUPLE, };
+#define HCLGE_FD_TUPLE_USER_DEF_TUPLES \ + (BIT(INNER_L2_RSV) | BIT(INNER_L3_RSV) | BIT(INNER_L4_RSV)) + enum HCLGE_FD_META_DATA { PACKET_TYPE_ID, IP_FRAGEMENT, @@ -572,6 +576,11 @@ struct key_info { #define MAX_KEY_BYTES (MAX_KEY_DWORDS * 4) #define MAX_META_DATA_LENGTH 32
+#define HCLGE_FD_MAX_USER_DEF_OFFSET 9000 +#define HCLGE_FD_USER_DEF_DATA GENMASK(15, 0) +#define HCLGE_FD_USER_DEF_OFFSET GENMASK(15, 0) +#define HCLGE_FD_USER_DEF_OFFSET_UNMASK GENMASK(15, 0) + /* assigned by firmware, the real filter number for each pf may be less */ #define MAX_FD_FILTER_NUM 4096 #define HCLGE_ARFS_EXPIRE_INTERVAL 5UL @@ -601,6 +610,26 @@ enum HCLGE_FD_NODE_STATE { HCLGE_FD_DELETED, };
+enum HCLGE_FD_USER_DEF_LAYER { + HCLGE_FD_USER_DEF_NONE, + HCLGE_FD_USER_DEF_L2, + HCLGE_FD_USER_DEF_L3, + HCLGE_FD_USER_DEF_L4, +}; + +#define HCLGE_FD_USER_DEF_LAYER_NUM 3 +struct hclge_fd_user_def_cfg { + u16 ref_cnt; + u16 offset; +}; + +struct hclge_fd_user_def_info { + enum HCLGE_FD_USER_DEF_LAYER layer; + u16 data; + u16 data_mask; + u16 offset; +}; + struct hclge_fd_key_cfg { u8 key_sel; u8 inner_sipv6_word_en; @@ -617,6 +646,7 @@ struct hclge_fd_cfg { u32 rule_num[MAX_STAGE_NUM]; /* rule entry number */ u16 cnt_num[MAX_STAGE_NUM]; /* rule hit counter number */ struct hclge_fd_key_cfg key_cfg[MAX_STAGE_NUM]; + struct hclge_fd_user_def_cfg user_def_cfg[HCLGE_FD_USER_DEF_LAYER_NUM]; };
#define IPV4_INDEX 3 @@ -633,6 +663,9 @@ struct hclge_fd_rule_tuples { u16 dst_port; u16 vlan_tag1; u16 ether_proto; + u16 l2_user_def; + u16 l3_user_def; + u32 l4_user_def; u8 ip_tos; u8 ip_proto; }; @@ -651,6 +684,9 @@ struct hclge_fd_rule { struct { u16 flow_id; /* only used for arfs */ } arfs; + struct { + struct hclge_fd_user_def_info user_def; + } ep; }; u16 queue_id; u16 vf_id;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 43f8b9333d86d4e3a42e55a6e41c78c249ac0216 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Vmdq is not supported yet, the num_vmdq_vport is always 0, it's a bit confusing when using the num_vport, so remove these unused codes of vmdq.
Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 2 - .../hisilicon/hns3/hns3pf/hclge_main.c | 240 +++++++----------- .../hisilicon/hns3/hns3pf/hclge_main.h | 2 - .../hisilicon/hns3/hns3vf/hclgevf_main.h | 1 - 4 files changed, 96 insertions(+), 149 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 565c5aa54f88..7feab8405d7c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -506,8 +506,6 @@ struct hclge_pf_res_cmd { #define HCLGE_CFG_RD_LEN_BYTES 16 #define HCLGE_CFG_RD_LEN_UNIT 4
-#define HCLGE_CFG_VMDQ_S 0 -#define HCLGE_CFG_VMDQ_M GENMASK(7, 0) #define HCLGE_CFG_TC_NUM_S 8 #define HCLGE_CFG_TC_NUM_M GENMASK(15, 8) #define HCLGE_CFG_TQP_DESC_N_S 16 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index aaee51ce4039..a1193cd462d7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1292,9 +1292,6 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc) req = (struct hclge_cfg_param_cmd *)desc[0].data;
/* get the configuration */ - cfg->vmdq_vport_num = hnae3_get_field(__le32_to_cpu(req->param[0]), - HCLGE_CFG_VMDQ_M, - HCLGE_CFG_VMDQ_S); cfg->tc_num = hnae3_get_field(__le32_to_cpu(req->param[0]), HCLGE_CFG_TC_NUM_M, HCLGE_CFG_TC_NUM_S); cfg->tqp_desc_num = hnae3_get_field(__le32_to_cpu(req->param[0]), @@ -1511,7 +1508,7 @@ static void hclge_init_kdump_kernel_config(struct hclge_dev *hdev) "Running kdump kernel. Using minimal resources\n");
/* minimal queue pairs equals to the number of vports */ - hdev->num_tqps = hdev->num_vmdq_vport + hdev->num_req_vfs + 1; + hdev->num_tqps = hdev->num_req_vfs + 1; hdev->num_tx_desc = HCLGE_MIN_TX_DESC; hdev->num_rx_desc = HCLGE_MIN_RX_DESC; } @@ -1526,7 +1523,6 @@ static int hclge_configure(struct hclge_dev *hdev) if (ret) return ret;
- hdev->num_vmdq_vport = cfg.vmdq_vport_num; hdev->base_tqp_pid = 0; hdev->vf_rss_size_max = cfg.vf_rss_size_max; hdev->pf_rss_size_max = cfg.pf_rss_size_max; @@ -1777,7 +1773,7 @@ static int hclge_map_tqp(struct hclge_dev *hdev) struct hclge_vport *vport = hdev->vport; u16 i, num_vport;
- num_vport = hdev->num_vmdq_vport + hdev->num_req_vfs + 1; + num_vport = hdev->num_req_vfs + 1; for (i = 0; i < num_vport; i++) { int ret;
@@ -1819,7 +1815,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev) int ret;
/* We need to alloc a vport for main NIC of PF */ - num_vport = hdev->num_vmdq_vport + hdev->num_req_vfs + 1; + num_vport = hdev->num_req_vfs + 1;
if (hdev->num_tqps < num_vport) { dev_err(&hdev->pdev->dev, "tqps(%u) is less than vports(%d)", @@ -2889,13 +2885,12 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status)
static void hclge_update_link_status(struct hclge_dev *hdev) { + struct hnae3_handle *rhandle = &hdev->vport[0].roce; + struct hnae3_handle *handle = &hdev->vport[0].nic; struct hnae3_client *rclient = hdev->roce_client; struct hnae3_client *client = hdev->nic_client; - struct hnae3_handle *rhandle; - struct hnae3_handle *handle; int state; int ret; - int i;
if (!client) return; @@ -2910,15 +2905,11 @@ static void hclge_update_link_status(struct hclge_dev *hdev) }
if (state != hdev->hw.mac.link) { - for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - handle = &hdev->vport[i].nic; - client->ops->link_status_change(handle, state); - hclge_config_mac_tnl_int(hdev, state); - rhandle = &hdev->vport[i].roce; - if (rclient && rclient->ops->link_status_change) - rclient->ops->link_status_change(rhandle, - state); - } + client->ops->link_status_change(handle, state); + hclge_config_mac_tnl_int(hdev, state); + if (rclient && rclient->ops->link_status_change) + rclient->ops->link_status_change(rhandle, state); + hdev->hw.mac.link = state; }
@@ -3498,8 +3489,9 @@ static void hclge_misc_irq_uninit(struct hclge_dev *hdev) int hclge_notify_client(struct hclge_dev *hdev, enum hnae3_reset_notify_type type) { + struct hnae3_handle *handle = &hdev->vport[0].nic; struct hnae3_client *client = hdev->nic_client; - u16 i; + int ret;
if (!test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state) || !client) return 0; @@ -3507,27 +3499,20 @@ int hclge_notify_client(struct hclge_dev *hdev, if (!client->ops->reset_notify) return -EOPNOTSUPP;
- for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - struct hnae3_handle *handle = &hdev->vport[i].nic; - int ret; - - ret = client->ops->reset_notify(handle, type); - if (ret) { - dev_err(&hdev->pdev->dev, - "notify nic client failed %d(%d)\n", type, ret); - return ret; - } - } + ret = client->ops->reset_notify(handle, type); + if (ret) + dev_err(&hdev->pdev->dev, "notify nic client failed %d(%d)\n", + type, ret);
- return 0; + return ret; }
static int hclge_notify_roce_client(struct hclge_dev *hdev, enum hnae3_reset_notify_type type) { + struct hnae3_handle *handle = &hdev->vport[0].roce; struct hnae3_client *client = hdev->roce_client; int ret; - u16 i;
if (!test_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state) || !client) return 0; @@ -3535,17 +3520,10 @@ static int hclge_notify_roce_client(struct hclge_dev *hdev, if (!client->ops->reset_notify) return -EOPNOTSUPP;
- for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - struct hnae3_handle *handle = &hdev->vport[i].roce; - - ret = client->ops->reset_notify(handle, type); - if (ret) { - dev_err(&hdev->pdev->dev, - "notify roce client failed %d(%d)", - type, ret); - return ret; - } - } + ret = client->ops->reset_notify(handle, type); + if (ret) + dev_err(&hdev->pdev->dev, "notify roce client failed %d(%d)", + type, ret);
return ret; } @@ -3613,7 +3591,7 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) { int i;
- for (i = hdev->num_vmdq_vport + 1; i < hdev->num_alloc_vport; i++) { + for (i = HCLGE_VF_VPORT_START_NUM; i < hdev->num_alloc_vport; i++) { struct hclge_vport *vport = &hdev->vport[i]; int ret;
@@ -3694,14 +3672,12 @@ void hclge_report_hw_error(struct hclge_dev *hdev, enum hnae3_hw_error_type type) { struct hnae3_client *client = hdev->nic_client; - u16 i;
if (!client || !client->ops->process_hw_error || !test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state)) return;
- for (i = 0; i < hdev->num_vmdq_vport + 1; i++) - client->ops->process_hw_error(&hdev->vport[i].nic, type); + client->ops->process_hw_error(&hdev->vport[0].nic, type); }
static void hclge_handle_imp_error(struct hclge_dev *hdev) @@ -4913,58 +4889,44 @@ int hclge_rss_init_hw(struct hclge_dev *hdev)
void hclge_rss_indir_init_cfg(struct hclge_dev *hdev) { - struct hclge_vport *vport = hdev->vport; - int i, j; + struct hclge_vport *vport = &hdev->vport[0]; + int i;
- for (j = 0; j < hdev->num_vmdq_vport + 1; j++) { - for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++) - vport[j].rss_indirection_tbl[i] = - i % vport[j].alloc_rss_size; - } + for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++) + vport->rss_indirection_tbl[i] = i % vport->alloc_rss_size; }
static int hclge_rss_init_cfg(struct hclge_dev *hdev) { u16 rss_ind_tbl_size = hdev->ae_dev->dev_specs.rss_ind_tbl_size; - int i, rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; - struct hclge_vport *vport = hdev->vport; + int rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; + struct hclge_vport *vport = &hdev->vport[0]; + u16 *rss_ind_tbl;
if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) rss_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
- for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - u16 *rss_ind_tbl; - - vport[i].rss_tuple_sets.ipv4_tcp_en = - HCLGE_RSS_INPUT_TUPLE_OTHER; - vport[i].rss_tuple_sets.ipv4_udp_en = - HCLGE_RSS_INPUT_TUPLE_OTHER; - vport[i].rss_tuple_sets.ipv4_sctp_en = - HCLGE_RSS_INPUT_TUPLE_SCTP; - vport[i].rss_tuple_sets.ipv4_fragment_en = - HCLGE_RSS_INPUT_TUPLE_OTHER; - vport[i].rss_tuple_sets.ipv6_tcp_en = - HCLGE_RSS_INPUT_TUPLE_OTHER; - vport[i].rss_tuple_sets.ipv6_udp_en = - HCLGE_RSS_INPUT_TUPLE_OTHER; - vport[i].rss_tuple_sets.ipv6_sctp_en = - hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 ? - HCLGE_RSS_INPUT_TUPLE_SCTP_NO_PORT : - HCLGE_RSS_INPUT_TUPLE_SCTP; - vport[i].rss_tuple_sets.ipv6_fragment_en = - HCLGE_RSS_INPUT_TUPLE_OTHER; - - vport[i].rss_algo = rss_algo; - - rss_ind_tbl = devm_kcalloc(&hdev->pdev->dev, rss_ind_tbl_size, - sizeof(*rss_ind_tbl), GFP_KERNEL); - if (!rss_ind_tbl) - return -ENOMEM; + vport->rss_tuple_sets.ipv4_tcp_en = HCLGE_RSS_INPUT_TUPLE_OTHER; + vport->rss_tuple_sets.ipv4_udp_en = HCLGE_RSS_INPUT_TUPLE_OTHER; + vport->rss_tuple_sets.ipv4_sctp_en = HCLGE_RSS_INPUT_TUPLE_SCTP; + vport->rss_tuple_sets.ipv4_fragment_en = HCLGE_RSS_INPUT_TUPLE_OTHER; + vport->rss_tuple_sets.ipv6_tcp_en = HCLGE_RSS_INPUT_TUPLE_OTHER; + vport->rss_tuple_sets.ipv6_udp_en = HCLGE_RSS_INPUT_TUPLE_OTHER; + vport->rss_tuple_sets.ipv6_sctp_en = + hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 ? + HCLGE_RSS_INPUT_TUPLE_SCTP_NO_PORT : + HCLGE_RSS_INPUT_TUPLE_SCTP; + vport->rss_tuple_sets.ipv6_fragment_en = HCLGE_RSS_INPUT_TUPLE_OTHER; + + vport->rss_algo = rss_algo; + + rss_ind_tbl = devm_kcalloc(&hdev->pdev->dev, rss_ind_tbl_size, + sizeof(*rss_ind_tbl), GFP_KERNEL); + if (!rss_ind_tbl) + return -ENOMEM;
- vport[i].rss_indirection_tbl = rss_ind_tbl; - memcpy(vport[i].rss_hash_key, hclge_hash_key, - HCLGE_RSS_KEY_SIZE); - } + vport->rss_indirection_tbl = rss_ind_tbl; + memcpy(vport->rss_hash_key, hclge_hash_key, HCLGE_RSS_KEY_SIZE);
hclge_rss_indir_init_cfg(hdev);
@@ -9130,7 +9092,7 @@ static bool hclge_check_vf_mac_exist(struct hclge_vport *vport, int vf_idx, return true;
vf_idx += HCLGE_VF_VPORT_START_NUM; - for (i = hdev->num_vmdq_vport + 1; i < hdev->num_alloc_vport; i++) + for (i = HCLGE_VF_VPORT_START_NUM; i < hdev->num_alloc_vport; i++) if (i != vf_idx && ether_addr_equal(mac_addr, hdev->vport[i].vf_info.mac)) return true; @@ -10771,7 +10733,6 @@ static void hclge_info_show(struct hclge_dev *hdev) dev_info(dev, "Desc num per TX queue: %u\n", hdev->num_tx_desc); dev_info(dev, "Desc num per RX queue: %u\n", hdev->num_rx_desc); dev_info(dev, "Numbers of vports: %u\n", hdev->num_alloc_vport); - dev_info(dev, "Numbers of vmdp vports: %u\n", hdev->num_vmdq_vport); dev_info(dev, "Numbers of VF for this PF: %u\n", hdev->num_req_vfs); dev_info(dev, "HW tc map: 0x%x\n", hdev->hw_tc_map); dev_info(dev, "Total buffer size for TX/RX: %u\n", hdev->pkt_buf_size); @@ -10886,39 +10847,35 @@ static int hclge_init_client_instance(struct hnae3_client *client, struct hnae3_ae_dev *ae_dev) { struct hclge_dev *hdev = ae_dev->priv; - struct hclge_vport *vport; - int i, ret; - - for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - vport = &hdev->vport[i]; + struct hclge_vport *vport = &hdev->vport[0]; + int ret;
- switch (client->type) { - case HNAE3_CLIENT_KNIC: - hdev->nic_client = client; - vport->nic.client = client; - ret = hclge_init_nic_client_instance(ae_dev, vport); - if (ret) - goto clear_nic; + switch (client->type) { + case HNAE3_CLIENT_KNIC: + hdev->nic_client = client; + vport->nic.client = client; + ret = hclge_init_nic_client_instance(ae_dev, vport); + if (ret) + goto clear_nic;
- ret = hclge_init_roce_client_instance(ae_dev, vport); - if (ret) - goto clear_roce; + ret = hclge_init_roce_client_instance(ae_dev, vport); + if (ret) + goto clear_roce;
- break; - case HNAE3_CLIENT_ROCE: - if (hnae3_dev_roce_supported(hdev)) { - hdev->roce_client = client; - vport->roce.client = client; - } + break; + case HNAE3_CLIENT_ROCE: + if (hnae3_dev_roce_supported(hdev)) { + hdev->roce_client = client; + vport->roce.client = client; + }
- ret = hclge_init_roce_client_instance(ae_dev, vport); - if (ret) - goto clear_roce; + ret = hclge_init_roce_client_instance(ae_dev, vport); + if (ret) + goto clear_roce;
- break; - default: - return -EINVAL; - } + break; + default: + return -EINVAL; }
return 0; @@ -10937,32 +10894,27 @@ static void hclge_uninit_client_instance(struct hnae3_client *client, struct hnae3_ae_dev *ae_dev) { struct hclge_dev *hdev = ae_dev->priv; - struct hclge_vport *vport; - int i; + struct hclge_vport *vport = &hdev->vport[0];
- for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { - vport = &hdev->vport[i]; - if (hdev->roce_client) { - clear_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state); - while (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) - msleep(HCLGE_WAIT_RESET_DONE); - - hdev->roce_client->ops->uninit_instance(&vport->roce, - 0); - hdev->roce_client = NULL; - vport->roce.client = NULL; - } - if (client->type == HNAE3_CLIENT_ROCE) - return; - if (hdev->nic_client && client->ops->uninit_instance) { - clear_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state); - while (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) - msleep(HCLGE_WAIT_RESET_DONE); - - client->ops->uninit_instance(&vport->nic, 0); - hdev->nic_client = NULL; - vport->nic.client = NULL; - } + if (hdev->roce_client) { + clear_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state); + while (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + msleep(HCLGE_WAIT_RESET_DONE); + + hdev->roce_client->ops->uninit_instance(&vport->roce, 0); + hdev->roce_client = NULL; + vport->roce.client = NULL; + } + if (client->type == HNAE3_CLIENT_ROCE) + return; + if (hdev->nic_client && client->ops->uninit_instance) { + clear_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state); + while (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + msleep(HCLGE_WAIT_RESET_DONE); + + client->ops->uninit_instance(&vport->nic, 0); + hdev->nic_client = NULL; + vport->nic.client = NULL; } }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 97e77e2f7539..dc3d29d41848 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -348,7 +348,6 @@ struct hclge_tc_info { };
struct hclge_cfg { - u8 vmdq_vport_num; u8 tc_num; u16 tqp_desc_num; u16 rx_buf_len; @@ -811,7 +810,6 @@ struct hclge_dev { struct hclge_rst_stats rst_stats; struct semaphore reset_sem; /* protect reset process */ u32 fw_version; - u16 num_vmdq_vport; /* Num vmdq vport this PF has set up */ u16 num_tqps; /* Num task queue pairs of this PF */ u16 num_req_vfs; /* Num VFs requested for this PF */
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 8c27ecd819af..ade6e7f5be5b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -192,7 +192,6 @@ struct hclgevf_tqp { };
struct hclgevf_cfg { - u8 vmdq_vport_num; u8 tc_num; u16 tqp_desc_num; u16 rx_buf_len;
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit c0127115ee2329dd57a65dceb139ec7cc39f48c7 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Remove some redundant blank lines.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 7 ------- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 1 - drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 2 -- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 5 ----- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 1 - drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 2 -- 6 files changed, 18 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c4a045987c2f..2967dea85eaf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -210,7 +210,6 @@ void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector, * Rl defines rate of interrupts i.e. number of interrupts-per-second * GL and RL(Rate Limiter) are 2 ways to acheive interrupt coalescing */ - if (rl_reg > 0 && !tqp_vector->tx_group.coal.adapt_enable && !tqp_vector->rx_group.coal.adapt_enable) /* According to the hardware, the range of rl_reg is @@ -882,7 +881,6 @@ static void hns3_set_outer_l2l3l4(struct sk_buff *skb, u8 ol4_proto, hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_S, HNS3_OL3T_IPV4_NO_CSUM); - } else if (skb->protocol == htons(ETH_P_IPV6)) { hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_S, HNS3_OL3T_IPV6); @@ -1291,7 +1289,6 @@ static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size, return UINT_MAX;
bd_num = hns3_skb_bd_num(skb, bd_size, bd_num); - if (!skb_has_frag_list(skb) || bd_num > HNS3_MAX_TSO_BD_NUM) return bd_num;
@@ -2995,7 +2992,6 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, HNS3_RXD_L3ID_S); l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M, HNS3_RXD_L4ID_S); - /* Can checksum ipv4 or ipv6 + UDP/TCP/SCTP packets */ if ((l3_type == HNS3_L3_TYPE_IPV4 || l3_type == HNS3_L3_TYPE_IPV6) && @@ -3325,7 +3321,6 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring)
if (!skb) { bd_base_info = le32_to_cpu(desc->rx.bd_base_info); - /* Check valid BD */ if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B)))) return -ENXIO; @@ -3587,7 +3582,6 @@ static int hns3_nic_common_poll(struct napi_struct *napi, int budget) hns3_for_each_ring(ring, tqp_vector->rx_group) { int rx_cleaned = hns3_clean_rx_ring(ring, rx_budget, hns3_rx_skb); - if (rx_cleaned >= rx_budget) clean_complete = false;
@@ -4055,7 +4049,6 @@ static void hns3_init_ring_hw(struct hns3_enet_ring *ring) hns3_buf_size2type(ring->buf_size)); hns3_write_dev(q, HNS3_RING_RX_RING_BD_NUM_REG, ring->desc_num / 8 - 1); - } else { hns3_write_dev(q, HNS3_RING_TX_RING_BASEADDR_L_REG, (u32)dma); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 3284a2cb52e6..76a482456f1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -366,7 +366,6 @@ static void hclge_parse_capability(struct hclge_dev *hdev, u32 caps;
caps = __le32_to_cpu(cmd->caps[0]); - if (hnae3_get_bit(caps, HCLGE_CAP_UDP_GSO_B)) set_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_PTP_B)) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 78d3eb142df8..8ee0a45095af 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1498,7 +1498,6 @@ hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) }
status = le32_to_cpu(desc[0].data[0]); - if (status & HCLGE_ROCEE_AXI_ERR_INT_MASK) { if (status & HCLGE_ROCEE_RERR_INT_MASK) dev_err(dev, "ROCEE RAS AXI rresp error\n"); @@ -1648,7 +1647,6 @@ pci_ers_result_t hclge_handle_hw_ras_error(struct hnae3_ae_dev *ae_dev) }
status = hclge_read_dev(&hdev->hw, HCLGE_RAS_PF_OTHER_INT_STS_REG); - if (status & HCLGE_RAS_REG_NFE_MASK || status & HCLGE_RAS_REG_ROCEE_ERR_MASK) ae_dev->hw_err_reset_req = 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index a1193cd462d7..906a1dc87ae9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -553,7 +553,6 @@ static int hclge_mac_update_stats(struct hclge_dev *hdev) int ret;
ret = hclge_mac_query_reg_num(hdev, &desc_num); - /* The firmware supports the new statistics acquisition method */ if (!ret) ret = hclge_mac_update_stats_complete(hdev, desc_num); @@ -784,7 +783,6 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) count += 1; handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK; } - } else if (stringset == ETH_SS_STATS) { count = ARRAY_SIZE(g_mac_stats_string) + hclge_tqps_get_sset_count(handle, stringset); @@ -2191,7 +2189,6 @@ static int hclge_only_alloc_priv_buff(struct hclge_dev *hdev, COMPENSATE_HALF_MPS_NUM * half_mps; min_rx_priv = round_up(min_rx_priv, HCLGE_BUF_SIZE_UNIT); rx_priv = round_down(rx_priv, HCLGE_BUF_SIZE_UNIT); - if (rx_priv < min_rx_priv) return false;
@@ -8608,7 +8605,6 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport, if (status) return status; status = hclge_add_mac_vlan_tbl(vport, &req, desc); - /* if already overflow, not to print each time */ if (status == -ENOSPC && !(vport->overflow_promisc_flags & HNAE3_OVERFLOW_MPE)) @@ -8657,7 +8653,6 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport, else /* Not all the vfid is zero, update the vfid */ status = hclge_add_mac_vlan_tbl(vport, &req, desc); - } else if (status == -ENOENT) { status = 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 46700c427849..d8c5c5810b99 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -349,7 +349,6 @@ static void hclgevf_parse_capability(struct hclgevf_dev *hdev, u32 caps;
caps = __le32_to_cpu(cmd->caps[0]); - if (hnae3_get_bit(caps, HCLGEVF_CAP_UDP_GSO_B)) set_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGEVF_CAP_INT_QL_B)) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 14b83eca0a5e..ae9507e8fb69 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -497,7 +497,6 @@ void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state)
link_state = test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state; - if (link_state != hdev->hw.mac.link) { client->ops->link_status_change(handle, !!link_state); if (rclient && rclient->ops->link_status_change) @@ -2356,7 +2355,6 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, /* fetch the events from their corresponding regs */ cmdq_stat_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_VECTOR0_CMDQ_STATE_REG); - if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_stat_reg) { rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING); dev_info(&hdev->pdev->dev,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit d914971df022e7abdb5f8fdfd901a655c9786c05 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
According to the HW manual, the query operation is unnecessary when the TM QCN error event is enabled, so remove it.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 8ee0a45095af..8223d699cd94 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -866,13 +866,7 @@ static int hclge_config_tm_hw_err_int(struct hclge_dev *hdev, bool en) }
/* configure TM QCN hw errors */ - ret = hclge_cmd_query_error(hdev, &desc, HCLGE_TM_QCN_MEM_INT_CFG, 0); - if (ret) { - dev_err(dev, "fail(%d) to read TM QCN CFG status\n", ret); - return ret; - } - - hclge_cmd_reuse_desc(&desc, false); + hclge_cmd_setup_basic_desc(&desc, HCLGE_TM_QCN_MEM_INT_CFG, false); if (en) desc.data[1] = cpu_to_le32(HCLGE_TM_QCN_MEM_ERR_INT_EN);
From: Peng Li lipeng321@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 567d1dd3e4bc204e424553ccf2e1d47b0f5d03a8 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Parameter vf in hclge_set_vf_vlan_common() is unused now, so remove it.
Signed-off-by: Peng Li lipeng321@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 906a1dc87ae9..0adaa30fa1d7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -9468,8 +9468,7 @@ static int hclge_check_vf_vlan_cmd_status(struct hclge_dev *hdev, u16 vfid, }
static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid, - bool is_kill, u16 vlan, - __be16 proto) + bool is_kill, u16 vlan) { struct hclge_vport *vport = &hdev->vport[vfid]; struct hclge_desc desc[2]; @@ -9535,8 +9534,7 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, if (is_kill && !vlan_id) return 0;
- ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id, - proto); + ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id); if (ret) { dev_err(&hdev->pdev->dev, "Set %u vport vlan filter config fail, ret =%d.\n",
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 1e49432b91d671fd690a6a99fcc082ae44b79faf category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Parameter cm_buf is never used, so remove it.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 1c699131e8df..85d306459e36 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1541,8 +1541,7 @@ static void hclge_dbg_dump_ncl_config(struct hclge_dev *hdev, } }
-static void hclge_dbg_dump_loopback(struct hclge_dev *hdev, - const char *cmd_buf) +static void hclge_dbg_dump_loopback(struct hclge_dev *hdev) { struct phy_device *phydev = hdev->hw.mac.phydev; struct hclge_config_mac_mode_cmd *req_app; @@ -1778,7 +1777,7 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_mac_tnl_status(hdev); } else if (strncmp(cmd_buf, DUMP_LOOPBACK, strlen(DUMP_LOOPBACK)) == 0) { - hclge_dbg_dump_loopback(hdev, &cmd_buf[sizeof(DUMP_LOOPBACK)]); + hclge_dbg_dump_loopback(hdev); } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { hclge_dbg_dump_qs_shaper(hdev, &cmd_buf[sizeof("dump qs shaper")]);
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit a1e144d7dc3c55aa4d451e3a23cd8f34cd65ee01 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Correct a report warning in hns3_ethtool.c
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 74a97daf7080..b48faf769b1c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -309,7 +309,7 @@ static int hns3_lp_run_test(struct net_device *ndev, enum hnae3_loop mode) }
/** - * hns3_nic_self_test - self test + * hns3_self_test - self test * @ndev: net device * @eth_test: test cmd * @data: test result
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit f7be24f00702cf07d025c79ab30a15f7d7db5cac category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
s/sucessful/successful/ s/serivce/service/ and remove a redundant new.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 0adaa30fa1d7..c3a9afdc435d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2217,7 +2217,7 @@ static int hclge_only_alloc_priv_buff(struct hclge_dev *hdev, /* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs * @hdev: pointer to struct hclge_dev * @buf_alloc: pointer to buffer calculation data - * @return: 0: calculate sucessful, negative: fail + * @return: 0: calculate successful, negative: fail */ static int hclge_rx_buffer_calc(struct hclge_dev *hdev, struct hclge_pkt_buf_alloc *buf_alloc) @@ -3358,7 +3358,7 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) * caused this event. Therefore, we will do below for now: * 1. Assert HNAE3_UNKNOWN_RESET type of reset. This means we * have defered type of reset to be used. - * 2. Schedule the reset serivce task. + * 2. Schedule the reset service task. * 3. When service task receives HNAE3_UNKNOWN_RESET type it * will fetch the correct type of reset. This would be done * by first decoding the types of errors. @@ -8416,7 +8416,7 @@ int hclge_update_mac_list(struct hclge_vport *vport,
/* if the mac addr is already in the mac list, no need to add a new * one into it, just check the mac addr state, convert it to a new - * new state, or just remove it, or do nothing. + * state, or just remove it, or do nothing. */ mac_node = hclge_find_mac_node(list, addr); if (mac_node) {
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 74d439b74ad3e05780d4cf3ab047345b443f7e67 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
hclge_reset_rebuild() is a bit too long. So add a new function hclge_update_reset_level() to improve readability.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c3a9afdc435d..4dee9886a027 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3940,6 +3940,21 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev) return false; }
+static void hclge_update_reset_level(struct hclge_dev *hdev) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + enum hnae3_reset_type reset_level; + + /* if default_reset_request has a higher level reset request, + * it should be handled as soon as possible. since some errors + * need this kind of reset to fix. + */ + reset_level = hclge_get_reset_level(ae_dev, + &hdev->default_reset_request); + if (reset_level != HNAE3_NONE_RESET) + set_bit(reset_level, &hdev->reset_request); +} + static int hclge_set_rst_done(struct hclge_dev *hdev) { struct hclge_pf_rst_done_cmd *req; @@ -4027,8 +4042,6 @@ static int hclge_reset_prepare(struct hclge_dev *hdev)
static int hclge_reset_rebuild(struct hclge_dev *hdev) { - struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); - enum hnae3_reset_type reset_level; int ret;
hdev->rst_stats.hw_reset_done_cnt++; @@ -4072,14 +4085,7 @@ static int hclge_reset_rebuild(struct hclge_dev *hdev) hdev->rst_stats.reset_done_cnt++; clear_bit(HCLGE_STATE_RST_FAIL, &hdev->state);
- /* if default_reset_request has a higher level reset request, - * it should be handled as soon as possible. since some errors - * need this kind of reset to fix. - */ - reset_level = hclge_get_reset_level(ae_dev, - &hdev->default_reset_request); - if (reset_level != HNAE3_NONE_RESET) - set_bit(reset_level, &hdev->reset_request); + hclge_update_reset_level(hdev);
return 0; }
From: Guojia Liao liaoguojia@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit b1261897b0902d870c483fb006a9443723a3d58b category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
hclge_tm_vport_tc_info_update() is bloated, so split it into separate functions for readability and maintainability.
Signed-off-by: Guojia Liao liaoguojia@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 151afd1f0688..aa81b8c56fce 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -631,13 +631,12 @@ static u16 hclge_vport_get_tqp_num(struct hclge_vport *vport) return sum; }
-static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) +static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; u16 vport_max_rss_size; u16 max_rss_size; - u8 i;
/* TC configuration is shared by PF/VF in one port, only allow * one tc for VF for simplicity. VF's vport_id is non zero. @@ -677,7 +676,15 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) /* Set to the maximum specification value (max_rss_size). */ kinfo->rss_size = max_rss_size; } +} + +static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) +{ + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; + struct hclge_dev *hdev = vport->back; + u8 i;
+ hclge_tm_update_kinfo_rss_size(vport); kinfo->num_tqps = hclge_vport_get_tqp_num(vport); vport->dwrr = 100; /* 100 percent as init */ vport->alloc_rss_size = kinfo->rss_size;
From: Liu Jian liujian56@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 54422bd436e084e6c74aff6026c1767f1570ab26 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c: In function 'hclge_clear_arfs_rules': drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c:7173:1: error: no return statement in function returning non-void [-Werror=return-type] 7173 | } | ^ cc1: some warnings being treated as errors make[6]: *** [scripts/Makefile.build:273: drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.o] Error 1 make[5]: *** [scripts/Makefile.build:534: drivers/net/ethernet/hisilicon/hns3/hns3pf] Error 2 make[4]: *** [scripts/Makefile.build:534: drivers/net/ethernet/hisilicon/hns3] Error 2 make[4]: *** Waiting for unfinished jobs.... make[3]: *** [scripts/Makefile.build:534: drivers/net/ethernet/hisilicon] Error 2 make[2]: *** [scripts/Makefile.build:534: drivers/net/ethernet] Error 2 make[1]: *** [scripts/Makefile.build:534: drivers/net] Error 2 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:1980: drivers] Error 2
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Liu Jian liujian56@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 4dee9886a027..ce67ccd28f1b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7133,8 +7133,8 @@ static int hclge_clear_arfs_rules(struct hclge_dev *hdev) } hclge_sync_fd_state(hdev);
- return 0; #endif + return 0; }
static void hclge_get_cls_key_basic(const struct flow_rule *flow,
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 989f7178b06666ec23ada614b2047c21d85b2a0a category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, when adding flow director rule, it missed to set rule state. Which may cause the rule state in software is unconsistent with hardware.
Fixes: fc4243b8de8b ("net: hns3: refactor flow director configuration") Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index ce67ccd28f1b..bee674cafeba 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6439,7 +6439,8 @@ static int hclge_add_fd_entry_common(struct hclge_dev *hdev, if (ret) goto out;
- hclge_update_fd_list(hdev, HCLGE_FD_ACTIVE, rule->location, rule); + rule->state = HCLGE_FD_ACTIVE; + hclge_update_fd_list(hdev, rule->state, rule->location, rule); hdev->fd_active_type = rule->rule_type;
out: @@ -7002,6 +7003,7 @@ static void hclge_fd_build_arfs_rule(const struct hclge_fd_rule_tuples *tuples, rule->action = 0; rule->vf_id = 0; rule->rule_type = HCLGE_FD_ARFS_ACTIVE; + rule->state = HCLGE_FD_TO_ADD; if (tuples->ether_proto == ETH_P_IP) { if (tuples->ip_proto == IPPROTO_TCP) rule->flow_type = TCP_V4_FLOW; @@ -7064,8 +7066,7 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id, rule->arfs.flow_id = flow_id; rule->queue_id = queue_id; hclge_fd_build_arfs_rule(&new_tuples, rule); - hclge_update_fd_list(hdev, HCLGE_FD_TO_ADD, rule->location, - rule); + hclge_update_fd_list(hdev, rule->state, rule->location, rule); hdev->fd_active_type = HCLGE_FD_ARFS_ACTIVE; } else if (rule->queue_id != queue_id) { rule->queue_id = queue_id;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 64ff58fa3bfcf26bc893ea425a0553b561ca5298 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
When new rule state is TO_ADD or ACTIVE, and there is already a rule with same location in the fd_rule_list, the new rule will be freed after modifying the old rule. It may cause user-after-free issue when access rule again in hclge_add_fd_entry_common().
Fixes: fc4243b8de8b ("net: hns3: refactor flow director configuration") Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index bee674cafeba..a814fab9d54d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6440,8 +6440,8 @@ static int hclge_add_fd_entry_common(struct hclge_dev *hdev, goto out;
rule->state = HCLGE_FD_ACTIVE; - hclge_update_fd_list(hdev, rule->state, rule->location, rule); hdev->fd_active_type = rule->rule_type; + hclge_update_fd_list(hdev, rule->state, rule->location, rule);
out: spin_unlock_bh(&hdev->fd_rule_lock);
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 5be36fb7855442e0299cf483d40457315a84cdf1 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, if user hasn't change channel number, the rss_size is limited to be no more than the vector number, in order to keep one vector only being mapped to one queue. But the queue number of each tc can be different, and one vector also can be mapped by multiple queues. So remove this limitation.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 9 --------- 1 file changed, 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index aa81b8c56fce..ebb962bad451 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -664,15 +664,6 @@ static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport) kinfo->rss_size = kinfo->req_rss_size; } else if (kinfo->rss_size > max_rss_size || (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) { - /* if user not set rss, the rss_size should compare with the - * valid msi numbers to ensure one to one map between tqp and - * irq as default. - */ - if (!kinfo->req_rss_size) - max_rss_size = min_t(u16, max_rss_size, - (hdev->num_nic_msi - 1) / - kinfo->tc_info.num_tc); - /* Set to the maximum specification value (max_rss_size). */ kinfo->rss_size = max_rss_size; }
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 8fa865510069aa1364f50761d38418dec4c163df category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the queue reset process needs to be performed one by one, which is inefficient. However, the queue reset of the same function is always performed at the same time. Therefore, according to the UM, command HCLGE_OPC_CFG_RST_TRIGGER can be used to reset all queues of the same function at a time, in order to optimize the queue reset process.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 8 +- .../hisilicon/hns3/hns3pf/hclge_main.c | 185 ++++++++++-------- .../hisilicon/hns3/hns3pf/hclge_main.h | 3 +- .../hisilicon/hns3/hns3pf/hclge_mbx.c | 26 ++- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 59 ++++-- 7 files changed, 182 insertions(+), 109 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 0d1a28b81991..da749d16dcc5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -578,7 +578,7 @@ struct hnae3_ae_ops { int vector_num, struct hnae3_ring_chain_node *vr_chain);
- int (*reset_queue)(struct hnae3_handle *handle, u16 queue_id); + int (*reset_queue)(struct hnae3_handle *handle); u32 (*get_fw_version)(struct hnae3_handle *handle); void (*get_mdix_mode)(struct hnae3_handle *handle, u8 *tp_mdix_ctrl, u8 *tp_mdix); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 2967dea85eaf..a3b961d8a726 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4486,11 +4486,11 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h) int i, j; int ret;
- for (i = 0; i < h->kinfo.num_tqps; i++) { - ret = h->ae_algo->ops->reset_queue(h, i); - if (ret) - return ret; + ret = h->ae_algo->ops->reset_queue(h); + if (ret) + return ret;
+ for (i = 0; i < h->kinfo.num_tqps; i++) { hns3_init_ring_hw(&priv->ring[i]);
/* We need to clear tx ring here because self test will diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 7feab8405d7c..c6fc22e29581 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -948,10 +948,16 @@ struct hclge_reset_tqp_queue_cmd {
#define HCLGE_CFG_RESET_MAC_B 3 #define HCLGE_CFG_RESET_FUNC_B 7 +#define HCLGE_CFG_RESET_RCB_B 1 struct hclge_reset_cmd { u8 mac_func_reset; u8 fun_reset_vfid; - u8 rsv[22]; + u8 fun_reset_rcb; + u8 rsv; + __le16 fun_reset_rcb_vqid_start; + __le16 fun_reset_rcb_vqid_num; + u8 fun_reset_rcb_return_status; + u8 rsv1[15]; };
#define HCLGE_PF_RESET_DONE_BIT BIT(0) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index a814fab9d54d..bc805d5fb16e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7797,13 +7797,12 @@ static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en) return ret; }
-static int hclge_tqp_enable(struct hclge_dev *hdev, unsigned int tqp_id, - int stream_id, bool enable) +static int hclge_tqp_enable_cmd_send(struct hclge_dev *hdev, u16 tqp_id, + u16 stream_id, bool enable) { struct hclge_desc desc; struct hclge_cfg_com_tqp_queue_cmd *req = (struct hclge_cfg_com_tqp_queue_cmd *)desc.data; - int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false); req->tqp_id = cpu_to_le16(tqp_id); @@ -7811,20 +7810,30 @@ static int hclge_tqp_enable(struct hclge_dev *hdev, unsigned int tqp_id, if (enable) req->enable |= 1U << HCLGE_TQP_ENABLE_B;
- ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - dev_err(&hdev->pdev->dev, - "Tqp enable fail, status =%d.\n", ret); - return ret; + return hclge_cmd_send(&hdev->hw, &desc, 1); +} + +static int hclge_tqp_enable(struct hnae3_handle *handle, bool enable) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int ret; + u16 i; + + for (i = 0; i < handle->kinfo.num_tqps; i++) { + ret = hclge_tqp_enable_cmd_send(hdev, i, 0, enable); + if (ret) + return ret; + } + return 0; }
static int hclge_set_loopback(struct hnae3_handle *handle, enum hnae3_loop loop_mode, bool en) { struct hclge_vport *vport = hclge_get_vport(handle); - struct hnae3_knic_private_info *kinfo; struct hclge_dev *hdev = vport->back; - int i, ret; + int ret;
/* Loopback can be enabled in three places: SSU, MAC, and serdes. By * default, SSU loopback is enabled, so if the SMAC and the DMAC are @@ -7861,14 +7870,12 @@ static int hclge_set_loopback(struct hnae3_handle *handle, if (ret) return ret;
- kinfo = &vport->nic.kinfo; - for (i = 0; i < kinfo->num_tqps; i++) { - ret = hclge_tqp_enable(hdev, i, 0, en); - if (ret) - return ret; - } + ret = hclge_tqp_enable(handle, en); + if (ret) + dev_err(&hdev->pdev->dev, "failed to %s tqp in loopback, ret = %d\n", + en ? "enable" : "disable", ret);
- return 0; + return ret; }
static int hclge_set_default_loopback(struct hclge_dev *hdev) @@ -7955,7 +7962,6 @@ static void hclge_ae_stop(struct hnae3_handle *handle) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - int i;
set_bit(HCLGE_STATE_DOWN, &hdev->state); spin_lock_bh(&hdev->fd_rule_lock); @@ -7972,8 +7978,7 @@ static void hclge_ae_stop(struct hnae3_handle *handle) return; }
- for (i = 0; i < handle->kinfo.num_tqps; i++) - hclge_reset_tqp(handle, i); + hclge_reset_tqp(handle);
hclge_config_mac_tnl_int(hdev, false);
@@ -10347,7 +10352,7 @@ int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu) return ret; }
-static int hclge_send_reset_tqp_cmd(struct hclge_dev *hdev, u16 queue_id, +static int hclge_reset_tqp_cmd_send(struct hclge_dev *hdev, u16 queue_id, bool enable) { struct hclge_reset_tqp_queue_cmd *req; @@ -10403,94 +10408,114 @@ u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id) return tqp->index; }
-int hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id) +static int hclge_reset_tqp_cmd(struct hnae3_handle *handle) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - int reset_try_times = 0; + u16 reset_try_times = 0; int reset_status; u16 queue_gid; int ret; + u16 i;
- queue_gid = hclge_covert_handle_qid_global(handle, queue_id); - - ret = hclge_tqp_enable(hdev, queue_id, 0, false); - if (ret) { - dev_err(&hdev->pdev->dev, "Disable tqp fail, ret = %d\n", ret); - return ret; - } + for (i = 0; i < handle->kinfo.num_tqps; i++) { + queue_gid = hclge_covert_handle_qid_global(handle, i); + ret = hclge_reset_tqp_cmd_send(hdev, queue_gid, true); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to send reset tqp cmd, ret = %d\n", + ret); + return ret; + }
- ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, true); - if (ret) { - dev_err(&hdev->pdev->dev, - "Send reset tqp cmd fail, ret = %d\n", ret); - return ret; - } + while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { + reset_status = hclge_get_reset_status(hdev, queue_gid); + if (reset_status) + break;
- while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { - reset_status = hclge_get_reset_status(hdev, queue_gid); - if (reset_status) - break; + /* Wait for tqp hw reset */ + usleep_range(1000, 1200); + }
- /* Wait for tqp hw reset */ - usleep_range(1000, 1200); - } + if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) { + dev_err(&hdev->pdev->dev, + "wait for tqp hw reset timeout\n"); + return -ETIME; + }
- if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) { - dev_err(&hdev->pdev->dev, "Reset TQP fail\n"); - return ret; + ret = hclge_reset_tqp_cmd_send(hdev, queue_gid, false); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to deassert soft reset, ret = %d\n", + ret); + return ret; + } + reset_try_times = 0; } - - ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, false); - if (ret) - dev_err(&hdev->pdev->dev, - "Deassert the soft reset fail, ret = %d\n", ret); - - return ret; + return 0; }
-void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id) +static int hclge_reset_rcb(struct hnae3_handle *handle) { - struct hnae3_handle *handle = &vport->nic; +#define HCLGE_RESET_RCB_NOT_SUPPORT 0U +#define HCLGE_RESET_RCB_SUCCESS 1U + + struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - int reset_try_times = 0; - int reset_status; + struct hclge_reset_cmd *req; + struct hclge_desc desc; + u8 return_status; u16 queue_gid; int ret;
- if (queue_id >= handle->kinfo.num_tqps) { - dev_warn(&hdev->pdev->dev, "Invalid vf queue id(%u)\n", - queue_id); - return; - } + queue_gid = hclge_covert_handle_qid_global(handle, 0);
- queue_gid = hclge_covert_handle_qid_global(&vport->nic, queue_id); + req = (struct hclge_reset_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_RST_TRIGGER, false); + hnae3_set_bit(req->fun_reset_rcb, HCLGE_CFG_RESET_RCB_B, 1); + req->fun_reset_rcb_vqid_start = cpu_to_le16(queue_gid); + req->fun_reset_rcb_vqid_num = cpu_to_le16(handle->kinfo.num_tqps);
- ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { - dev_warn(&hdev->pdev->dev, - "Send reset tqp cmd fail, ret = %d\n", ret); - return; + dev_err(&hdev->pdev->dev, + "failed to send rcb reset cmd, ret = %d\n", ret); + return ret; }
- while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { - reset_status = hclge_get_reset_status(hdev, queue_gid); - if (reset_status) - break; + return_status = req->fun_reset_rcb_return_status; + if (return_status == HCLGE_RESET_RCB_SUCCESS) + return 0;
- /* Wait for tqp hw reset */ - usleep_range(1000, 1200); + if (return_status != HCLGE_RESET_RCB_NOT_SUPPORT) { + dev_err(&hdev->pdev->dev, "failed to reset rcb, ret = %u\n", + return_status); + return -EIO; }
- if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) { - dev_warn(&hdev->pdev->dev, "Reset TQP fail\n"); - return; + /* if reset rcb cmd is unsupported, we need to send reset tqp cmd + * again to reset all tqps + */ + return hclge_reset_tqp_cmd(handle); +} + +int hclge_reset_tqp(struct hnae3_handle *handle) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int ret; + + /* only need to disable PF's tqp */ + if (!vport->vport_id) { + ret = hclge_tqp_enable(handle, false); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to disable tqp, ret = %d\n", ret); + return ret; + } }
- ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, false); - if (ret) - dev_warn(&hdev->pdev->dev, - "Deassert the soft reset fail, ret = %d\n", ret); + return hclge_reset_rcb(handle); }
static u32 hclge_get_fw_version(struct hnae3_handle *handle) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index dc3d29d41848..c1aaf7c534c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1053,8 +1053,7 @@ int hclge_rss_init_hw(struct hclge_dev *hdev); void hclge_rss_indir_init_cfg(struct hclge_dev *hdev);
void hclge_mbx_handler(struct hclge_dev *hdev); -int hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id); -void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id); +int hclge_reset_tqp(struct hnae3_handle *handle); int hclge_cfg_flowctrl(struct hclge_dev *hdev); int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id); int hclge_vport_start(struct hclge_vport *vport); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 9265a00de18e..384227b8ed9c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -550,14 +550,32 @@ static void hclge_get_link_mode(struct hclge_vport *vport, HCLGE_MBX_LINK_STAT_MODE, dest_vfid); }
-static void hclge_mbx_reset_vf_queue(struct hclge_vport *vport, - struct hclge_mbx_vf_to_pf_cmd *mbx_req) +static int hclge_mbx_reset_vf_queue(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *mbx_req, + struct hclge_respond_to_vf_msg *resp_msg) { +#define HCLGE_RESET_ALL_QUEUE_DONE 1U + struct hnae3_handle *handle = &vport->nic; + struct hclge_dev *hdev = vport->back; u16 queue_id; + int ret;
memcpy(&queue_id, mbx_req->msg.data, sizeof(queue_id)); + resp_msg->data[0] = HCLGE_RESET_ALL_QUEUE_DONE; + resp_msg->len = sizeof(u8);
- hclge_reset_vf_queue(vport, queue_id); + /* pf will reset vf's all queues at a time. So it is unnecessary + * to reset queues if queue_id > 0, just return success. + */ + if (queue_id > 0) + return 0; + + ret = hclge_reset_tqp(handle); + if (ret) + dev_err(&hdev->pdev->dev, "failed to reset vf %u queue, ret = %d\n", + vport->vport_id - HCLGE_VF_VPORT_START_NUM, ret); + + return ret; }
static int hclge_reset_vf(struct hclge_vport *vport) @@ -785,7 +803,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev) ret); break; case HCLGE_MBX_QUEUE_RESET: - hclge_mbx_reset_vf_queue(vport, req); + ret = hclge_mbx_reset_vf_queue(vport, req, &resp_msg); break; case HCLGE_MBX_RESET: ret = hclge_reset_vf(vport); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index ae9507e8fb69..56ca087b0015 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1240,12 +1240,11 @@ static void hclgevf_sync_promisc_mode(struct hclgevf_dev *hdev) } }
-static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, unsigned int tqp_id, - int stream_id, bool enable) +static int hclgevf_tqp_enable_cmd_send(struct hclgevf_dev *hdev, u16 tqp_id, + u16 stream_id, bool enable) { struct hclgevf_cfg_com_tqp_queue_cmd *req; struct hclgevf_desc desc; - int status;
req = (struct hclgevf_cfg_com_tqp_queue_cmd *)desc.data;
@@ -1256,12 +1255,22 @@ static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, unsigned int tqp_id, if (enable) req->enable |= 1U << HCLGEVF_TQP_ENABLE_B;
- status = hclgevf_cmd_send(&hdev->hw, &desc, 1); - if (status) - dev_err(&hdev->pdev->dev, - "TQP enable fail, status =%d.\n", status); + return hclgevf_cmd_send(&hdev->hw, &desc, 1); +}
- return status; +static int hclgevf_tqp_enable(struct hnae3_handle *handle, bool enable) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int ret; + u16 i; + + for (i = 0; i < handle->kinfo.num_tqps; i++) { + ret = hclgevf_tqp_enable_cmd_send(hdev, i, 0, enable); + if (ret) + return ret; + } + + return 0; }
static void hclgevf_reset_tqp_stats(struct hnae3_handle *handle) @@ -1710,20 +1719,39 @@ static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0); }
-static int hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id) +static int hclgevf_reset_tqp(struct hnae3_handle *handle) { +#define HCLGEVF_RESET_ALL_QUEUE_DONE 1U struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hclge_vf_to_pf_msg send_msg; + u8 return_status = 0; int ret; + u16 i;
/* disable vf queue before send queue reset msg to PF */ - ret = hclgevf_tqp_enable(hdev, queue_id, 0, false); - if (ret) + ret = hclgevf_tqp_enable(handle, false); + if (ret) { + dev_err(&hdev->pdev->dev, "failed to disable tqp, ret = %d\n", + ret); return ret; + }
hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0); - memcpy(send_msg.data, &queue_id, sizeof(queue_id)); - return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0); + + ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &return_status, + sizeof(return_status)); + if (ret || return_status == HCLGEVF_RESET_ALL_QUEUE_DONE) + return ret; + + for (i = 1; i < handle->kinfo.num_tqps; i++) { + hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0); + memcpy(send_msg.data, &i, sizeof(i)); + ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0); + if (ret) + return ret; + } + + return 0; }
static int hclgevf_set_mtu(struct hnae3_handle *handle, int new_mtu) @@ -2636,14 +2664,11 @@ static int hclgevf_ae_start(struct hnae3_handle *handle) static void hclgevf_ae_stop(struct hnae3_handle *handle) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - int i;
set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
if (hdev->reset_type != HNAE3_VF_RESET) - for (i = 0; i < handle->kinfo.num_tqps; i++) - if (hclgevf_reset_tqp(handle, i)) - break; + hclgevf_reset_tqp(handle);
hclgevf_reset_tqp_stats(handle); hclgevf_update_link_status(hdev, 0);
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 811c0830eb4ca8811ed80fe40378f622b9844835 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The actual size on wire for tso skb should be (gso_segs - 1) * hdr + skb->len instead of skb->len, which can be seen by user using 'ethtool -S ethX' cmd, and 'Byte Queue Limit' also use the send size stat to do the queue limiting, so add send_bytes in the desc_cb to record the actual send size for a skb. And send_bytes is only for tx desc_cb and page_offset is only for rx desc, so reuse the same space for both of them.
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 25 +++++++++++++------ .../net/ethernet/hisilicon/hns3/hns3_enet.h | 7 +++++- 2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a3b961d8a726..5ee207ff0b7e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -694,7 +694,7 @@ void hns3_enable_vlan_filter(struct net_device *netdev, bool enable) }
static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, - u16 *mss, u32 *type_cs_vlan_tso) + u16 *mss, u32 *type_cs_vlan_tso, u32 *send_bytes) { u32 l4_offset, hdr_len; union l3_hdr_info l3; @@ -750,6 +750,8 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, (__force __wsum)htonl(l4_paylen)); }
+ *send_bytes = (skb_shinfo(skb)->gso_segs - 1) * hdr_len + skb->len; + /* find the txbd field values */ *paylen_fdop_ol4cs = skb->len - hdr_len; hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_TSO_B, 1); @@ -1073,7 +1075,8 @@ static bool hns3_check_hw_tx_csum(struct sk_buff *skb) }
static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, - struct sk_buff *skb, struct hns3_desc *desc) + struct sk_buff *skb, struct hns3_desc *desc, + struct hns3_desc_cb *desc_cb) { u32 ol_type_vlan_len_msec = 0; u32 paylen_ol4cs = skb->len; @@ -1102,6 +1105,8 @@ static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, 1); }
+ desc_cb->send_bytes = skb->len; + if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 ol4_proto, il4_proto;
@@ -1137,7 +1142,7 @@ static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, }
ret = hns3_set_tso(skb, &paylen_ol4cs, &mss_hw_csum, - &type_cs_vlan_tso); + &type_cs_vlan_tso, &desc_cb->send_bytes); if (unlikely(ret < 0)) { u64_stats_update_begin(&ring->syncp); ring->stats.tx_tso_err++; @@ -1550,6 +1555,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping]; + struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; struct netdev_queue *dev_queue; int pre_ntu, next_to_use_head; bool doorbell; @@ -1577,7 +1583,8 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
next_to_use_head = ring->next_to_use;
- ret = hns3_fill_skb_desc(ring, skb, &ring->desc[ring->next_to_use]); + ret = hns3_fill_skb_desc(ring, skb, &ring->desc[ring->next_to_use], + desc_cb); if (unlikely(ret < 0)) goto fill_err;
@@ -1597,7 +1604,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Complete translate all packets */ dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); - doorbell = __netdev_tx_sent_queue(dev_queue, skb->len, + doorbell = __netdev_tx_sent_queue(dev_queue, desc_cb->send_bytes, netdev_xmit_more()); hns3_tx_doorbell(ring, ret, doorbell);
@@ -2718,8 +2725,12 @@ static bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring, break;
desc_cb = &ring->desc_cb[ntc]; - (*pkts) += (desc_cb->type == DESC_TYPE_SKB); - (*bytes) += desc_cb->length; + + if (desc_cb->type == DESC_TYPE_SKB) { + (*pkts)++; + (*bytes) += desc_cb->send_bytes; + } + /* desc_cb will be cleaned, after hnae3_free_buffer_detach */ hns3_free_buffer_detach(ring, ntc, budget);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index e44224e23315..daa04aeb0942 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -298,7 +298,12 @@ struct hns3_desc_cb {
/* priv data for the desc, e.g. skb when use with ip stack */ void *priv; - u32 page_offset; + + union { + u32 page_offset; /* for rx */ + u32 send_bytes; /* for tx */ + }; + u32 length; /* length of the buffer */
u16 reuse_flag;
From: Guojia Liao liaoguojia@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 33a8f7649913e4aeda34bc1294302688112c9c56 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The device HNAE3_DEVICE_VERSION_V3 supports up to 1280 queues and qsets for one function, so the bitwidth of tc_offset, meaning the tqps index, needs to expand from 10 bits to 11 bits.
The device HNAE3_DEVICE_VERSION_V3 supports up to 512 queues on one TC. The tc_size, meaning the exponent with base 2 of queues supported on TC, which needs to expand from 3 bits to 4 bits.
Signed-off-by: Guojia Liao liaoguojia@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 7 +++++-- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 8a37a22a176b..c6dc11b32aa7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -223,11 +223,14 @@ struct hclgevf_rss_indirection_table_cmd { };
#define HCLGEVF_RSS_TC_OFFSET_S 0 -#define HCLGEVF_RSS_TC_OFFSET_M (0x3ff << HCLGEVF_RSS_TC_OFFSET_S) +#define HCLGEVF_RSS_TC_OFFSET_M GENMASK(10, 0) +#define HCLGEVF_RSS_TC_SIZE_MSB_B 11 #define HCLGEVF_RSS_TC_SIZE_S 12 -#define HCLGEVF_RSS_TC_SIZE_M (0x7 << HCLGEVF_RSS_TC_SIZE_S) +#define HCLGEVF_RSS_TC_SIZE_M GENMASK(14, 12) #define HCLGEVF_RSS_TC_VALID_B 15 #define HCLGEVF_MAX_TC_NUM 8 +#define HCLGEVF_RSS_TC_SIZE_MSB_OFFSET 3 + struct hclgevf_rss_tc_mode_cmd { __le16 rss_tc_mode[HCLGEVF_MAX_TC_NUM]; u8 rsv[8]; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 56ca087b0015..9838cc75e4c8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -706,6 +706,9 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) (tc_valid[i] & 0x1)); hnae3_set_field(mode, HCLGEVF_RSS_TC_SIZE_M, HCLGEVF_RSS_TC_SIZE_S, tc_size[i]); + hnae3_set_bit(mode, HCLGEVF_RSS_TC_SIZE_MSB_B, + tc_size[i] >> HCLGEVF_RSS_TC_SIZE_MSB_OFFSET & + 0x1); hnae3_set_field(mode, HCLGEVF_RSS_TC_OFFSET_M, HCLGEVF_RSS_TC_OFFSET_S, tc_offset[i]);
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 97b9e5c131f16e2e487139ba596f9e6df927ae87 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
skb_put_padto() may fails because of memory failure, sw_err_cnt is already used to log memory failure in hns3_skb_linearize(), so use it to log the memory failure for skb_put_padto() too.
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 5ee207ff0b7e..28e6660bcb56 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1564,6 +1564,11 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) /* Hardware can only handle short frames above 32 bytes */ if (skb_put_padto(skb, HNS3_MIN_TX_LEN)) { hns3_tx_doorbell(ring, 0, !netdev_xmit_more()); + + u64_stats_update_begin(&ring->syncp); + ring->stats.sw_err_cnt++; + u64_stats_update_end(&ring->syncp); + return NETDEV_TX_OK; }
From: Salil Mehta salil.mehta@huawei.com
mainline inclusion from mainline-v5.12-rc7 commit 0600771fa6b231e801ba1ff5d7adfcf7659dbbf3 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Code to defer the reset(which caps the frequency of the reset) schedules the timer and returns. Hence, following 'else-if' looks un-necessary.
Fixes: 9de0b86f6444 ("net: hns3: Prevent to request reset frequently") Signed-off-by: Salil Mehta salil.mehta@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index b19e637f8a64..94adec64cb3b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4132,7 +4132,9 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) HCLGE_RESET_INTERVAL))) { mod_timer(&hdev->reset_timer, jiffies + HCLGE_RESET_INTERVAL); return; - } else if (hdev->default_reset_request) { + } + + if (hdev->default_reset_request) { hdev->reset_level = hclge_get_reset_level(ae_dev, &hdev->default_reset_request);
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 715c58e94f0d78907bfccde12c2ca5236502c53e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To implement the system suspend/resume functions, the NIC driver needs to support: 1. When the system enters the suspend mode, the driver needs to implement the suspend callback function of the NIC device. The driver needs to mute the device, stop all RX/TX activities of the device, and unmap the interrupt. 2. When the system enters the resume mode, the driver needs to implement the resume callback function of the NIC device and restore the device to the state before suspension.
When the system enters the suspend and resume mode, the NIC driver actually executes the PF function reset process.
When the PFs are suspending/resuming, VFs also enter the suspend/resume state because the PFs trigger the VFs to reset, therefore no operation is required when the VF pci_driver is suspending or resuming.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 29 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 2 ++ 2 files changed, 31 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index e1ffcbe52265..3c4726f1de98 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2362,6 +2362,32 @@ static void hns3_shutdown(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D3hot); }
+static int __maybe_unused hns3_suspend(struct device *dev) +{ + struct hnae3_ae_dev *ae_dev = dev_get_drvdata(dev); + + if (hns3_is_phys_func(ae_dev->pdev)) { + dev_info(dev, "Begin to suspend.\n"); + if (ae_dev && ae_dev->ops && ae_dev->ops->reset_prepare) + ae_dev->ops->reset_prepare(ae_dev, HNAE3_FUNC_RESET); + } + + return 0; +} + +static int __maybe_unused hns3_resume(struct device *dev) +{ + struct hnae3_ae_dev *ae_dev = dev_get_drvdata(dev); + + if (hns3_is_phys_func(ae_dev->pdev)) { + dev_info(dev, "Begin to resume.\n"); + if (ae_dev && ae_dev->ops && ae_dev->ops->reset_done) + ae_dev->ops->reset_done(ae_dev); + } + + return 0; +} + static pci_ers_result_t hns3_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { @@ -2440,12 +2466,15 @@ static const struct pci_error_handlers hns3_err_handler = { .reset_done = hns3_reset_done, };
+static SIMPLE_DEV_PM_OPS(hns3_pm_ops, hns3_suspend, hns3_resume); + static struct pci_driver hns3_driver = { .name = hns3_driver_name, .id_table = hns3_pci_tbl, .probe = hns3_probe, .remove = hns3_remove, .shutdown = hns3_shutdown, + .driver.pm = &hns3_pm_ops, .sriov_configure = hns3_pci_sriov_configure, .err_handler = &hns3_err_handler, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 8ac77a370643..497def85ea12 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11093,6 +11093,8 @@ static void hclge_reset_prepare_general(struct hnae3_ae_dev *ae_dev,
if (hdev->reset_type == HNAE3_FLR_RESET) hdev->rst_stats.flr_rst_cnt++; + else if (hdev->reset_type == HNAE3_FUNC_RESET) + hdev->rst_stats.pf_rst_cnt++; }
static void hclge_reset_done(struct hnae3_ae_dev *ae_dev)
From: Salil Mehta salil.mehta@huawei.com
mainline inclusion from mainline-v5.12-rc7 commit cd7e963d2f0875789ddb5c3746b628716bd0a8c9 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Some trivial spelling mistakes which caught my eye during the review of the code.
Signed-off-by: Salil Mehta salil.mehta@huawei.com Link: https://lore.kernel.org/r/20210409074223.32480-1-salil.mehta@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 497def85ea12..1c17fdc780e9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11790,7 +11790,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, if (ret) return ret;
- /* RSS indirection table has been configuared by user */ + /* RSS indirection table has been configured by user */ if (rxfh_configured) goto out;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 49e6acaa863a..07aa26ba0966 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2226,7 +2226,7 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
if (test_and_clear_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state)) { - /* PF has initmated that it is about to reset the hardware. + /* PF has intimated that it is about to reset the hardware. * We now have to poll & check if hardware has actually * completed the reset sequence. On hardware reset completion, * VF needs to reset the client and ae device. @@ -3526,7 +3526,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, if (ret) return ret;
- /* RSS indirection table has been configuared by user */ + /* RSS indirection table has been configured by user */ if (rxfh_configured) goto out;
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 18b6e31f8bf4ac7af7b057228f38a5a530378e4e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Previously, VF updates its link status every second by send query command to PF in periodic service task. If link stats of PF is changed, VF may need at most one second to update its link status.
To reduce delay of link status between PF and VFs, PF actively push its link status to VFs when its link status is updated. And to let VF know PF supports this new feature, the link status changed mailbox command adds one bit to indicate it.
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 3 ++ .../hisilicon/hns3/hns3pf/hclge_main.c | 35 ++++++++++++++++++- .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + .../hisilicon/hns3/hns3pf/hclge_mbx.c | 12 +++---- 4 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 33defa4c180a..a2c17af57fde 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -172,4 +172,7 @@ struct hclgevf_mbx_arq_ring { (arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) #define hclge_mbx_head_ptr_move_arq(arq) \ (arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) + +/* PF immediately push link status to VFs when link status changed */ +#define HCLGE_MBX_PUSH_LINK_STATUS_EN BIT(0) #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 1c17fdc780e9..dc06986055e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2880,6 +2880,28 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status) return hclge_get_mac_link_status(hdev, link_status); }
+static void hclge_push_link_status(struct hclge_dev *hdev) +{ + struct hclge_vport *vport; + int ret; + u16 i; + + for (i = 0; i < pci_num_vf(hdev->pdev); i++) { + vport = &hdev->vport[i + HCLGE_VF_VPORT_START_NUM]; + + if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state) || + vport->vf_info.link_state != IFLA_VF_LINK_STATE_AUTO) + continue; + + ret = hclge_push_vf_link_status(vport); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to push link status to vf%u, ret = %d\n", + i, ret); + } + } +} + static void hclge_update_link_status(struct hclge_dev *hdev) { struct hnae3_handle *rhandle = &hdev->vport[0].roce; @@ -2908,6 +2930,7 @@ static void hclge_update_link_status(struct hclge_dev *hdev) rclient->ops->link_status_change(rhandle, state);
hdev->hw.mac.link = state; + hclge_push_link_status(hdev); }
clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); @@ -3246,14 +3269,24 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf, { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + int link_state_old; + int ret;
vport = hclge_get_vf_vport(hdev, vf); if (!vport) return -EINVAL;
+ link_state_old = vport->vf_info.link_state; vport->vf_info.link_state = link_state;
- return 0; + ret = hclge_push_vf_link_status(vport); + if (ret) { + vport->vf_info.link_state = link_state_old; + dev_err(&hdev->pdev->dev, + "failed to push vf%d link status, ret = %d\n", vf, ret); + } + + return ret; }
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index c1aaf7c534c9..ff1d47308c2d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1089,4 +1089,5 @@ void hclge_report_hw_error(struct hclge_dev *hdev, enum hnae3_hw_error_type type); void hclge_inform_vf_promisc_info(struct hclge_vport *vport); void hclge_dbg_dump_rst_info(struct hclge_dev *hdev); +int hclge_push_vf_link_status(struct hclge_vport *vport); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 384227b8ed9c..f1c9f4ada348 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -490,16 +490,14 @@ static void hclge_get_vf_media_type(struct hclge_vport *vport, resp_msg->len = HCLGE_VF_MEDIA_TYPE_LENGTH; }
-static int hclge_get_link_info(struct hclge_vport *vport, - struct hclge_mbx_vf_to_pf_cmd *mbx_req) +int hclge_push_vf_link_status(struct hclge_vport *vport) { #define HCLGE_VF_LINK_STATE_UP 1U #define HCLGE_VF_LINK_STATE_DOWN 0U
struct hclge_dev *hdev = vport->back; u16 link_status; - u8 msg_data[8]; - u8 dest_vfid; + u8 msg_data[9]; u16 duplex;
/* mac.link can only be 0 or 1 */ @@ -520,11 +518,11 @@ static int hclge_get_link_info(struct hclge_vport *vport, memcpy(&msg_data[0], &link_status, sizeof(u16)); memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32)); memcpy(&msg_data[6], &duplex, sizeof(u16)); - dest_vfid = mbx_req->mbx_src_vfid; + msg_data[8] = HCLGE_MBX_PUSH_LINK_STATUS_EN;
/* send this requested info to VF */ return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), - HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid); + HCLGE_MBX_LINK_STAT_CHANGE, vport->vport_id); }
static void hclge_get_link_mode(struct hclge_vport *vport, @@ -796,7 +794,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev) hclge_get_vf_tcinfo(vport, &resp_msg); break; case HCLGE_MBX_GET_LINK_STATUS: - ret = hclge_get_link_info(vport, req); + ret = hclge_push_vf_link_status(vport); if (ret) dev_err(&hdev->pdev->dev, "failed to inform link stat to VF, ret = %d\n",
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 1c5a2ba67989c01b8aeda81969b7a4a3702c51b5 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
When enter suspend mode the counter of pf reset will be increased twice, since both hclge_prepare_general() and hclge_prepare_wait() increase this counter. So remove the duplicate counting in hclge_prepare_general().
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index dc06986055e4..c296ab64fb0a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11126,8 +11126,6 @@ static void hclge_reset_prepare_general(struct hnae3_ae_dev *ae_dev,
if (hdev->reset_type == HNAE3_FLR_RESET) hdev->rst_stats.flr_rst_cnt++; - else if (hdev->reset_type == HNAE3_FUNC_RESET) - hdev->rst_stats.pf_rst_cnt++; }
static void hclge_reset_done(struct hnae3_ae_dev *ae_dev)
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.13-rc1 commit 8ed64dbe0bdf39479772896b2b4e5cbbdf89f086 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Modify some inappropriate spaces in comments of struct hlcgevf_tqp_stats.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 956095b89a1b..265c9b0b4728 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -177,9 +177,9 @@ struct hclgevf_hw {
/* TQP stats */ struct hlcgevf_tqp_stats { - /* query_tqp_tx_queue_statistics ,opcode id: 0x0B03 */ + /* query_tqp_tx_queue_statistics, opcode id: 0x0B03 */ u64 rcb_tx_ring_pktnum_rcd; /* 32bit */ - /* query_tqp_rx_queue_statistics ,opcode id: 0x0B13 */ + /* query_tqp_rx_queue_statistics, opcode id: 0x0B13 */ u64 rcb_rx_ring_pktnum_rcd; /* 32bit */ };
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 796640778c26f3d99fde173bb7b1d726b5f0d816 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the driver gets packet type by parsing the L3_ID/L4_ID/OL3_ID/OL4_ID from RX descriptor, it's time-consuming.
Now some new devices support RXD advanced layout, which combines previous OL3_ID/OL4_ID to 8bit ptype field, so the driver gets packet type by looking up only one table, and L3_ID/L4_ID become reserved fields.
Considering compatibility, the firmware will report capability of RXD advanced layout, the driver will identify and enable it by default. This patch provides basic function: identify and enable the RXD advanced layout, and refactor out hns3_rx_checksum() by using ptype table to handle RX checksum if supported.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 3 + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 358 ++++++++++++++++-- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 12 + .../hisilicon/hns3/hns3pf/hclge_cmd.c | 2 + .../hisilicon/hns3/hns3pf/hclge_cmd.h | 1 + .../hisilicon/hns3/hns3pf/hclge_main.c | 17 + .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + .../hisilicon/hns3/hns3vf/hclgevf_cmd.c | 2 + .../hisilicon/hns3/hns3vf/hclgevf_cmd.h | 1 + .../hisilicon/hns3/hns3vf/hclgevf_main.c | 17 + .../hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + 12 files changed, 393 insertions(+), 26 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index f690ce9f4985..87928f8d089c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -90,6 +90,7 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_STASH_B, HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, HNAE3_DEV_SUPPORT_PAUSE_B, + HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, };
#define hnae3_dev_fd_supported(hdev) \ @@ -140,6 +141,9 @@ enum HNAE3_DEV_CAP_BITS { #define hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev) \ test_bit(HNAE3_DEV_SUPPORT_TQP_TXRX_INDEP_B, (ae_dev)->caps)
+#define hnae3_ae_dev_rxd_adv_layout_supported(ae_dev) \ + test_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, (ae_dev)->caps) + #define ring_ptr_move_fw(ring, p) \ ((ring)->p = ((ring)->p + 1) % (ring)->desc_num) #define ring_ptr_move_bw(ring, p) \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 9d702bd0c7c1..e58a2c1f7c1c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -367,6 +367,9 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h) "yes" : "no"); dev_info(&h->pdev->dev, "support imp-controlled PHY: %s\n", test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, caps) ? "yes" : "no"); + dev_info(&h->pdev->dev, "support rxd advanced layout: %s\n", + test_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, caps) ? + "yes" : "no"); }
static void hns3_dbg_dev_specs(struct hnae3_handle *h) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index e1a32e023d82..5093444bae60 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -91,6 +91,278 @@ static const struct pci_device_id hns3_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, hns3_pci_tbl);
+#define HNS3_RX_PTYPE_ENTRY(ptype, l, s, t) \ + { ptype, \ + l, \ + CHECKSUM_##s, \ + HNS3_L3_TYPE_##t, \ + 1 } + +#define HNS3_RX_PTYPE_UNUSED_ENTRY(ptype) \ + { ptype, 0, CHECKSUM_NONE, HNS3_L3_TYPE_PARSE_FAIL, 0 } + +static const struct hns3_rx_ptype hns3_rx_ptype_tbl[] = { + HNS3_RX_PTYPE_UNUSED_ENTRY(0), + HNS3_RX_PTYPE_ENTRY(1, 0, COMPLETE, ARP), + HNS3_RX_PTYPE_ENTRY(2, 0, COMPLETE, RARP), + HNS3_RX_PTYPE_ENTRY(3, 0, COMPLETE, LLDP), + HNS3_RX_PTYPE_ENTRY(4, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(5, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(6, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(7, 0, COMPLETE, CNM), + HNS3_RX_PTYPE_ENTRY(8, 0, NONE, PARSE_FAIL), + HNS3_RX_PTYPE_UNUSED_ENTRY(9), + HNS3_RX_PTYPE_UNUSED_ENTRY(10), + HNS3_RX_PTYPE_UNUSED_ENTRY(11), + HNS3_RX_PTYPE_UNUSED_ENTRY(12), + HNS3_RX_PTYPE_UNUSED_ENTRY(13), + HNS3_RX_PTYPE_UNUSED_ENTRY(14), + HNS3_RX_PTYPE_UNUSED_ENTRY(15), + HNS3_RX_PTYPE_ENTRY(16, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(17, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(18, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(19, 0, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(20, 0, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(21, 0, NONE, IPV4), + HNS3_RX_PTYPE_ENTRY(22, 0, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(23, 0, NONE, IPV4), + HNS3_RX_PTYPE_ENTRY(24, 0, NONE, IPV4), + HNS3_RX_PTYPE_ENTRY(25, 0, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_UNUSED_ENTRY(26), + HNS3_RX_PTYPE_UNUSED_ENTRY(27), + HNS3_RX_PTYPE_UNUSED_ENTRY(28), + HNS3_RX_PTYPE_ENTRY(29, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(30, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(31, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(32, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(33, 1, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(34, 1, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(35, 1, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(36, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(37, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_UNUSED_ENTRY(38), + HNS3_RX_PTYPE_ENTRY(39, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(40, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(41, 1, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(42, 1, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(43, 1, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(44, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(45, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_UNUSED_ENTRY(46), + HNS3_RX_PTYPE_UNUSED_ENTRY(47), + HNS3_RX_PTYPE_UNUSED_ENTRY(48), + HNS3_RX_PTYPE_UNUSED_ENTRY(49), + HNS3_RX_PTYPE_UNUSED_ENTRY(50), + HNS3_RX_PTYPE_UNUSED_ENTRY(51), + HNS3_RX_PTYPE_UNUSED_ENTRY(52), + HNS3_RX_PTYPE_UNUSED_ENTRY(53), + HNS3_RX_PTYPE_UNUSED_ENTRY(54), + HNS3_RX_PTYPE_UNUSED_ENTRY(55), + HNS3_RX_PTYPE_UNUSED_ENTRY(56), + HNS3_RX_PTYPE_UNUSED_ENTRY(57), + HNS3_RX_PTYPE_UNUSED_ENTRY(58), + HNS3_RX_PTYPE_UNUSED_ENTRY(59), + HNS3_RX_PTYPE_UNUSED_ENTRY(60), + HNS3_RX_PTYPE_UNUSED_ENTRY(61), + HNS3_RX_PTYPE_UNUSED_ENTRY(62), + HNS3_RX_PTYPE_UNUSED_ENTRY(63), + HNS3_RX_PTYPE_UNUSED_ENTRY(64), + HNS3_RX_PTYPE_UNUSED_ENTRY(65), + HNS3_RX_PTYPE_UNUSED_ENTRY(66), + HNS3_RX_PTYPE_UNUSED_ENTRY(67), + HNS3_RX_PTYPE_UNUSED_ENTRY(68), + HNS3_RX_PTYPE_UNUSED_ENTRY(69), + HNS3_RX_PTYPE_UNUSED_ENTRY(70), + HNS3_RX_PTYPE_UNUSED_ENTRY(71), + HNS3_RX_PTYPE_UNUSED_ENTRY(72), + HNS3_RX_PTYPE_UNUSED_ENTRY(73), + HNS3_RX_PTYPE_UNUSED_ENTRY(74), + HNS3_RX_PTYPE_UNUSED_ENTRY(75), + HNS3_RX_PTYPE_UNUSED_ENTRY(76), + HNS3_RX_PTYPE_UNUSED_ENTRY(77), + HNS3_RX_PTYPE_UNUSED_ENTRY(78), + HNS3_RX_PTYPE_UNUSED_ENTRY(79), + HNS3_RX_PTYPE_UNUSED_ENTRY(80), + HNS3_RX_PTYPE_UNUSED_ENTRY(81), + HNS3_RX_PTYPE_UNUSED_ENTRY(82), + HNS3_RX_PTYPE_UNUSED_ENTRY(83), + HNS3_RX_PTYPE_UNUSED_ENTRY(84), + HNS3_RX_PTYPE_UNUSED_ENTRY(85), + HNS3_RX_PTYPE_UNUSED_ENTRY(86), + HNS3_RX_PTYPE_UNUSED_ENTRY(87), + HNS3_RX_PTYPE_UNUSED_ENTRY(88), + HNS3_RX_PTYPE_UNUSED_ENTRY(89), + HNS3_RX_PTYPE_UNUSED_ENTRY(90), + HNS3_RX_PTYPE_UNUSED_ENTRY(91), + HNS3_RX_PTYPE_UNUSED_ENTRY(92), + HNS3_RX_PTYPE_UNUSED_ENTRY(93), + HNS3_RX_PTYPE_UNUSED_ENTRY(94), + HNS3_RX_PTYPE_UNUSED_ENTRY(95), + HNS3_RX_PTYPE_UNUSED_ENTRY(96), + HNS3_RX_PTYPE_UNUSED_ENTRY(97), + HNS3_RX_PTYPE_UNUSED_ENTRY(98), + HNS3_RX_PTYPE_UNUSED_ENTRY(99), + HNS3_RX_PTYPE_UNUSED_ENTRY(100), + HNS3_RX_PTYPE_UNUSED_ENTRY(101), + HNS3_RX_PTYPE_UNUSED_ENTRY(102), + HNS3_RX_PTYPE_UNUSED_ENTRY(103), + HNS3_RX_PTYPE_UNUSED_ENTRY(104), + HNS3_RX_PTYPE_UNUSED_ENTRY(105), + HNS3_RX_PTYPE_UNUSED_ENTRY(106), + HNS3_RX_PTYPE_UNUSED_ENTRY(107), + HNS3_RX_PTYPE_UNUSED_ENTRY(108), + HNS3_RX_PTYPE_UNUSED_ENTRY(109), + HNS3_RX_PTYPE_UNUSED_ENTRY(110), + HNS3_RX_PTYPE_ENTRY(111, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(112, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(113, 0, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(114, 0, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(115, 0, NONE, IPV6), + HNS3_RX_PTYPE_ENTRY(116, 0, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(117, 0, NONE, IPV6), + HNS3_RX_PTYPE_ENTRY(118, 0, NONE, IPV6), + HNS3_RX_PTYPE_ENTRY(119, 0, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_UNUSED_ENTRY(120), + HNS3_RX_PTYPE_UNUSED_ENTRY(121), + HNS3_RX_PTYPE_UNUSED_ENTRY(122), + HNS3_RX_PTYPE_ENTRY(123, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(124, 0, COMPLETE, PARSE_FAIL), + HNS3_RX_PTYPE_ENTRY(125, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(126, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(127, 1, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(128, 1, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(129, 1, UNNECESSARY, IPV4), + HNS3_RX_PTYPE_ENTRY(130, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_ENTRY(131, 0, COMPLETE, IPV4), + HNS3_RX_PTYPE_UNUSED_ENTRY(132), + HNS3_RX_PTYPE_ENTRY(133, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(134, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(135, 1, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(136, 1, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(137, 1, UNNECESSARY, IPV6), + HNS3_RX_PTYPE_ENTRY(138, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_ENTRY(139, 0, COMPLETE, IPV6), + HNS3_RX_PTYPE_UNUSED_ENTRY(140), + HNS3_RX_PTYPE_UNUSED_ENTRY(141), + HNS3_RX_PTYPE_UNUSED_ENTRY(142), + HNS3_RX_PTYPE_UNUSED_ENTRY(143), + HNS3_RX_PTYPE_UNUSED_ENTRY(144), + HNS3_RX_PTYPE_UNUSED_ENTRY(145), + HNS3_RX_PTYPE_UNUSED_ENTRY(146), + HNS3_RX_PTYPE_UNUSED_ENTRY(147), + HNS3_RX_PTYPE_UNUSED_ENTRY(148), + HNS3_RX_PTYPE_UNUSED_ENTRY(149), + HNS3_RX_PTYPE_UNUSED_ENTRY(150), + HNS3_RX_PTYPE_UNUSED_ENTRY(151), + HNS3_RX_PTYPE_UNUSED_ENTRY(152), + HNS3_RX_PTYPE_UNUSED_ENTRY(153), + HNS3_RX_PTYPE_UNUSED_ENTRY(154), + HNS3_RX_PTYPE_UNUSED_ENTRY(155), + HNS3_RX_PTYPE_UNUSED_ENTRY(156), + HNS3_RX_PTYPE_UNUSED_ENTRY(157), + HNS3_RX_PTYPE_UNUSED_ENTRY(158), + HNS3_RX_PTYPE_UNUSED_ENTRY(159), + HNS3_RX_PTYPE_UNUSED_ENTRY(160), + HNS3_RX_PTYPE_UNUSED_ENTRY(161), + HNS3_RX_PTYPE_UNUSED_ENTRY(162), + HNS3_RX_PTYPE_UNUSED_ENTRY(163), + HNS3_RX_PTYPE_UNUSED_ENTRY(164), + HNS3_RX_PTYPE_UNUSED_ENTRY(165), + HNS3_RX_PTYPE_UNUSED_ENTRY(166), + HNS3_RX_PTYPE_UNUSED_ENTRY(167), + HNS3_RX_PTYPE_UNUSED_ENTRY(168), + HNS3_RX_PTYPE_UNUSED_ENTRY(169), + HNS3_RX_PTYPE_UNUSED_ENTRY(170), + HNS3_RX_PTYPE_UNUSED_ENTRY(171), + HNS3_RX_PTYPE_UNUSED_ENTRY(172), + HNS3_RX_PTYPE_UNUSED_ENTRY(173), + HNS3_RX_PTYPE_UNUSED_ENTRY(174), + HNS3_RX_PTYPE_UNUSED_ENTRY(175), + HNS3_RX_PTYPE_UNUSED_ENTRY(176), + HNS3_RX_PTYPE_UNUSED_ENTRY(177), + HNS3_RX_PTYPE_UNUSED_ENTRY(178), + HNS3_RX_PTYPE_UNUSED_ENTRY(179), + HNS3_RX_PTYPE_UNUSED_ENTRY(180), + HNS3_RX_PTYPE_UNUSED_ENTRY(181), + HNS3_RX_PTYPE_UNUSED_ENTRY(182), + HNS3_RX_PTYPE_UNUSED_ENTRY(183), + HNS3_RX_PTYPE_UNUSED_ENTRY(184), + HNS3_RX_PTYPE_UNUSED_ENTRY(185), + HNS3_RX_PTYPE_UNUSED_ENTRY(186), + HNS3_RX_PTYPE_UNUSED_ENTRY(187), + HNS3_RX_PTYPE_UNUSED_ENTRY(188), + HNS3_RX_PTYPE_UNUSED_ENTRY(189), + HNS3_RX_PTYPE_UNUSED_ENTRY(190), + HNS3_RX_PTYPE_UNUSED_ENTRY(191), + HNS3_RX_PTYPE_UNUSED_ENTRY(192), + HNS3_RX_PTYPE_UNUSED_ENTRY(193), + HNS3_RX_PTYPE_UNUSED_ENTRY(194), + HNS3_RX_PTYPE_UNUSED_ENTRY(195), + HNS3_RX_PTYPE_UNUSED_ENTRY(196), + HNS3_RX_PTYPE_UNUSED_ENTRY(197), + HNS3_RX_PTYPE_UNUSED_ENTRY(198), + HNS3_RX_PTYPE_UNUSED_ENTRY(199), + HNS3_RX_PTYPE_UNUSED_ENTRY(200), + HNS3_RX_PTYPE_UNUSED_ENTRY(201), + HNS3_RX_PTYPE_UNUSED_ENTRY(202), + HNS3_RX_PTYPE_UNUSED_ENTRY(203), + HNS3_RX_PTYPE_UNUSED_ENTRY(204), + HNS3_RX_PTYPE_UNUSED_ENTRY(205), + HNS3_RX_PTYPE_UNUSED_ENTRY(206), + HNS3_RX_PTYPE_UNUSED_ENTRY(207), + HNS3_RX_PTYPE_UNUSED_ENTRY(208), + HNS3_RX_PTYPE_UNUSED_ENTRY(209), + HNS3_RX_PTYPE_UNUSED_ENTRY(210), + HNS3_RX_PTYPE_UNUSED_ENTRY(211), + HNS3_RX_PTYPE_UNUSED_ENTRY(212), + HNS3_RX_PTYPE_UNUSED_ENTRY(213), + HNS3_RX_PTYPE_UNUSED_ENTRY(214), + HNS3_RX_PTYPE_UNUSED_ENTRY(215), + HNS3_RX_PTYPE_UNUSED_ENTRY(216), + HNS3_RX_PTYPE_UNUSED_ENTRY(217), + HNS3_RX_PTYPE_UNUSED_ENTRY(218), + HNS3_RX_PTYPE_UNUSED_ENTRY(219), + HNS3_RX_PTYPE_UNUSED_ENTRY(220), + HNS3_RX_PTYPE_UNUSED_ENTRY(221), + HNS3_RX_PTYPE_UNUSED_ENTRY(222), + HNS3_RX_PTYPE_UNUSED_ENTRY(223), + HNS3_RX_PTYPE_UNUSED_ENTRY(224), + HNS3_RX_PTYPE_UNUSED_ENTRY(225), + HNS3_RX_PTYPE_UNUSED_ENTRY(226), + HNS3_RX_PTYPE_UNUSED_ENTRY(227), + HNS3_RX_PTYPE_UNUSED_ENTRY(228), + HNS3_RX_PTYPE_UNUSED_ENTRY(229), + HNS3_RX_PTYPE_UNUSED_ENTRY(230), + HNS3_RX_PTYPE_UNUSED_ENTRY(231), + HNS3_RX_PTYPE_UNUSED_ENTRY(232), + HNS3_RX_PTYPE_UNUSED_ENTRY(233), + HNS3_RX_PTYPE_UNUSED_ENTRY(234), + HNS3_RX_PTYPE_UNUSED_ENTRY(235), + HNS3_RX_PTYPE_UNUSED_ENTRY(236), + HNS3_RX_PTYPE_UNUSED_ENTRY(237), + HNS3_RX_PTYPE_UNUSED_ENTRY(238), + HNS3_RX_PTYPE_UNUSED_ENTRY(239), + HNS3_RX_PTYPE_UNUSED_ENTRY(240), + HNS3_RX_PTYPE_UNUSED_ENTRY(241), + HNS3_RX_PTYPE_UNUSED_ENTRY(242), + HNS3_RX_PTYPE_UNUSED_ENTRY(243), + HNS3_RX_PTYPE_UNUSED_ENTRY(244), + HNS3_RX_PTYPE_UNUSED_ENTRY(245), + HNS3_RX_PTYPE_UNUSED_ENTRY(246), + HNS3_RX_PTYPE_UNUSED_ENTRY(247), + HNS3_RX_PTYPE_UNUSED_ENTRY(248), + HNS3_RX_PTYPE_UNUSED_ENTRY(249), + HNS3_RX_PTYPE_UNUSED_ENTRY(250), + HNS3_RX_PTYPE_UNUSED_ENTRY(251), + HNS3_RX_PTYPE_UNUSED_ENTRY(252), + HNS3_RX_PTYPE_UNUSED_ENTRY(253), + HNS3_RX_PTYPE_UNUSED_ENTRY(254), + HNS3_RX_PTYPE_UNUSED_ENTRY(255), +}; + +#define HNS3_INVALID_PTYPE \ + ARRAY_SIZE(hns3_rx_ptype_tbl) + static irqreturn_t hns3_irq_handle(int irq, void *vector) { struct hns3_enet_tqp_vector *tqp_vector = vector; @@ -2992,35 +3264,15 @@ static void hns3_checksum_complete(struct hns3_enet_ring *ring, skb->csum = csum_unfold((__force __sum16)(lo | hi << 8)); }
-static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, - u32 l234info, u32 bd_base_info, u32 ol_info) +static void hns3_rx_handle_csum(struct sk_buff *skb, u32 l234info, + u32 ol_info, u32 ptype) { - struct net_device *netdev = ring_to_netdev(ring); int l3_type, l4_type; int ol4_type;
- skb->ip_summed = CHECKSUM_NONE; - - skb_checksum_none_assert(skb); - - if (!(netdev->features & NETIF_F_RXCSUM)) - return; - - if (l234info & BIT(HNS3_RXD_L2_CSUM_B)) { - hns3_checksum_complete(ring, skb, l234info); - return; - } - - /* check if hardware has done checksum */ - if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) - return; - - if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) | - BIT(HNS3_RXD_OL3E_B) | - BIT(HNS3_RXD_OL4E_B)))) { - u64_stats_update_begin(&ring->syncp); - ring->stats.l3l4_csum_err++; - u64_stats_update_end(&ring->syncp); + if (ptype != HNS3_INVALID_PTYPE) { + skb->csum_level = hns3_rx_ptype_tbl[ptype].csum_level; + skb->ip_summed = hns3_rx_ptype_tbl[ptype].ip_summed;
return; } @@ -3050,6 +3302,46 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, } }
+static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, + u32 l234info, u32 bd_base_info, u32 ol_info) +{ + struct net_device *netdev = ring_to_netdev(ring); + struct hns3_nic_priv *priv = netdev_priv(netdev); + u32 ptype = HNS3_INVALID_PTYPE; + + skb->ip_summed = CHECKSUM_NONE; + + skb_checksum_none_assert(skb); + + if (!(netdev->features & NETIF_F_RXCSUM)) + return; + + if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) + ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M, + HNS3_RXD_PTYPE_S); + + if (l234info & BIT(HNS3_RXD_L2_CSUM_B)) { + hns3_checksum_complete(ring, skb, l234info); + return; + } + + /* check if hardware has done checksum */ + if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) + return; + + if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) | + BIT(HNS3_RXD_OL3E_B) | + BIT(HNS3_RXD_OL4E_B)))) { + u64_stats_update_begin(&ring->syncp); + ring->stats.l3l4_csum_err++; + u64_stats_update_end(&ring->syncp); + + return; + } + + hns3_rx_handle_csum(skb, l234info, ol_info, ptype); +} + static void hns3_rx_skb(struct hns3_enet_ring *ring, struct sk_buff *skb) { if (skb_has_frag_list(skb)) @@ -3233,6 +3525,8 @@ static int hns3_set_gro_and_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, u32 l234info, u32 bd_base_info, u32 ol_info) { + struct net_device *netdev = ring_to_netdev(ring); + struct hns3_nic_priv *priv = netdev_priv(netdev); u32 l3_type;
skb_shinfo(skb)->gso_size = hnae3_get_field(bd_base_info, @@ -3248,7 +3542,16 @@ static int hns3_set_gro_and_checksum(struct hns3_enet_ring *ring, HNS3_RXD_GRO_COUNT_M, HNS3_RXD_GRO_COUNT_S);
- l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M, HNS3_RXD_L3ID_S); + if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) { + u32 ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M, + HNS3_RXD_PTYPE_S); + + l3_type = hns3_rx_ptype_tbl[ptype].l3_type; + } else { + l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M, + HNS3_RXD_L3ID_S); + } + if (l3_type == HNS3_L3_TYPE_IPV4) skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; else if (l3_type == HNS3_L3_TYPE_IPV6) @@ -4340,6 +4643,9 @@ static int hns3_client_init(struct hnae3_handle *handle) if (test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps)) set_bit(HNS3_NIC_STATE_HW_TX_CSUM_ENABLE, &priv->state);
+ if (hnae3_ae_dev_rxd_adv_layout_supported(ae_dev)) + set_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state); + set_bit(HNS3_NIC_STATE_INITED, &priv->state);
if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index daa04aeb0942..843642b9884b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -19,6 +19,7 @@ enum hns3_nic_state { HNS3_NIC_STATE_SERVICE_SCHED, HNS3_NIC_STATE2_RESET_REQUESTED, HNS3_NIC_STATE_HW_TX_CSUM_ENABLE, + HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, HNS3_NIC_STATE_MAX };
@@ -114,6 +115,9 @@ enum hns3_nic_state { #define HNS3_RXD_FBLI_S 14 #define HNS3_RXD_FBLI_M (0x3 << HNS3_RXD_FBLI_S)
+#define HNS3_RXD_PTYPE_S 4 +#define HNS3_RXD_PTYPE_M GENMASK(11, 4) + #define HNS3_RXD_BDTYPE_S 0 #define HNS3_RXD_BDTYPE_M (0xf << HNS3_RXD_BDTYPE_S) #define HNS3_RXD_VLD_B 4 @@ -366,6 +370,14 @@ enum hns3_pkt_ol4type { HNS3_OL4_TYPE_UNKNOWN };
+struct hns3_rx_ptype { + u32 ptype:8; + u32 csum_level:2; + u32 ip_summed:2; + u32 l3_type:4; + u32 valid:1; +}; + struct ring_stats { u64 sw_err_cnt; u64 seg_pkt_cnt; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 76a482456f1f..0df9ca311e6c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -386,6 +386,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_PHY_IMP_B)) set_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGE_CAP_RXD_ADV_LAYOUT_B)) + set_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, ae_dev->caps); }
static __le32 hclge_build_api_caps(void) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index c6fc22e29581..c6cd273363d5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -391,6 +391,7 @@ enum HCLGE_CAP_BITS { HCLGE_CAP_UDP_TUNNEL_CSUM_B, HCLGE_CAP_FEC_B = 13, HCLGE_CAP_PAUSE_B = 14, + HCLGE_CAP_RXD_ADV_LAYOUT_B = 15, };
enum HCLGE_API_CAP_BITS { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6304aed49f22..55b0453d3948 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11167,6 +11167,18 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev) } }
+static void hclge_init_rxd_adv_layout(struct hclge_dev *hdev) +{ + if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev)) + hclge_write_dev(&hdev->hw, HCLGE_RXD_ADV_LAYOUT_EN_REG, 1); +} + +static void hclge_uninit_rxd_adv_layout(struct hclge_dev *hdev) +{ + if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev)) + hclge_write_dev(&hdev->hw, HCLGE_RXD_ADV_LAYOUT_EN_REG, 0); +} + static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) { struct pci_dev *pdev = ae_dev->pdev; @@ -11339,6 +11351,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) mod_timer(&hdev->reset_timer, jiffies + HCLGE_RESET_INTERVAL); }
+ hclge_init_rxd_adv_layout(hdev); + /* Enable MISC vector(vector0) */ hclge_enable_vector(&hdev->misc_vector, true);
@@ -11720,6 +11734,8 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) if (ret) return ret;
+ hclge_init_rxd_adv_layout(hdev); + dev_info(&pdev->dev, "Reset done, %s driver initialization finished.\n", HCLGE_DRIVER_NAME);
@@ -11735,6 +11751,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_clear_vf_vlan(hdev); hclge_misc_affinity_teardown(hdev); hclge_state_uninit(hdev); + hclge_uninit_rxd_adv_layout(hdev); hclge_uninit_mac_table(hdev); hclge_del_all_fd_entries(hdev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index ff1d47308c2d..10f5c11e6b66 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -53,6 +53,7 @@ /* bar registers for common func */ #define HCLGE_VECTOR0_OTER_EN_REG 0x20600 #define HCLGE_GRO_EN_REG 0x28000 +#define HCLGE_RXD_ADV_LAYOUT_EN_REG 0x28008
/* bar registers for rcb */ #define HCLGE_RING_RX_ADDR_L_REG 0x80000 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index d8c5c5810b99..bd19a2d89f6c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -359,6 +359,8 @@ static void hclgevf_parse_capability(struct hclgevf_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGEVF_CAP_UDP_TUNNEL_CSUM_B)) set_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGEVF_CAP_RXD_ADV_LAYOUT_B)) + set_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, ae_dev->caps); }
static __le32 hclgevf_build_api_caps(void) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index c6dc11b32aa7..202feb70dba5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -159,6 +159,7 @@ enum HCLGEVF_CAP_BITS { HCLGEVF_CAP_HW_PAD_B, HCLGEVF_CAP_STASH_B, HCLGEVF_CAP_UDP_TUNNEL_CSUM_B, + HCLGEVF_CAP_RXD_ADV_LAYOUT_B = 15, };
enum HCLGEVF_API_CAP_BITS { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 0db51ef15ef6..7bef6b24e610 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -3242,6 +3242,18 @@ static int hclgevf_clear_vport_list(struct hclgevf_dev *hdev) return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0); }
+static void hclgevf_init_rxd_adv_layout(struct hclgevf_dev *hdev) +{ + if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev)) + hclgevf_write_dev(&hdev->hw, HCLGEVF_RXD_ADV_LAYOUT_EN_REG, 1); +} + +static void hclgevf_uninit_rxd_adv_layout(struct hclgevf_dev *hdev) +{ + if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev)) + hclgevf_write_dev(&hdev->hw, HCLGEVF_RXD_ADV_LAYOUT_EN_REG, 0); +} + static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) { struct pci_dev *pdev = hdev->pdev; @@ -3279,6 +3291,8 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
+ hclgevf_init_rxd_adv_layout(hdev); + dev_info(&hdev->pdev->dev, "Reset done\n");
return 0; @@ -3379,6 +3393,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) goto err_config; }
+ hclgevf_init_rxd_adv_layout(hdev); + hdev->last_reset_time = jiffies; dev_info(&hdev->pdev->dev, "finished initializing %s driver\n", HCLGEVF_DRIVER_NAME); @@ -3405,6 +3421,7 @@ static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev) struct hclge_vf_to_pf_msg send_msg;
hclgevf_state_uninit(hdev); + hclgevf_uninit_rxd_adv_layout(hdev);
hclgevf_build_send_msg(&send_msg, HCLGE_MBX_VF_UNINIT, 0); hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 265c9b0b4728..b146d04526de 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -47,6 +47,7 @@
/* bar registers for common func */ #define HCLGEVF_GRO_EN_REG 0x28000 +#define HCLGEVF_RXD_ADV_LAYOUT_EN_REG 0x28008
/* bar registers for rcb */ #define HCLGEVF_RING_RX_ADDR_L_REG 0x80000
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 1ddc028ac84988b6b1c9ceb9d15acbf321735ca3 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Only when RXD advanced layout is enabled, in some cases (e.g. ip fragments), the checksum of entire packet will be calculated and filled in the least significant 16 bits of the unused addr field.
So refactor out the handling of RX completion checksum: adjust the location of the checksum in RX descriptor, and use ptype table to identify whether this kind of checksum is calculated.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 10 ------ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 32 ++++++++++--------- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 12 +++---- 3 files changed, 22 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index e58a2c1f7c1c..e405fef81d15 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -260,16 +260,6 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf) dev_info(dev, "(RX)addr: %pad\n", &addr); dev_info(dev, "(RX)l234_info: %u\n", l234info);
- if (l234info & BIT(HNS3_RXD_L2_CSUM_B)) { - u32 lo, hi; - - lo = hnae3_get_field(l234info, HNS3_RXD_L2_CSUM_L_M, - HNS3_RXD_L2_CSUM_L_S); - hi = hnae3_get_field(l234info, HNS3_RXD_L2_CSUM_H_M, - HNS3_RXD_L2_CSUM_H_S); - dev_info(dev, "(RX)csum: %u\n", lo | hi << 8); - } - dev_info(dev, "(RX)pkt_len: %u\n", le16_to_cpu(rx_desc->rx.pkt_len)); dev_info(dev, "(RX)size: %u\n", le16_to_cpu(rx_desc->rx.size)); dev_info(dev, "(RX)rss_hash: %u\n", le32_to_cpu(rx_desc->rx.rss_hash)); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 5093444bae60..0899d21eea33 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3248,20 +3248,20 @@ static int hns3_gro_complete(struct sk_buff *skb, u32 l234info) return 0; }
-static void hns3_checksum_complete(struct hns3_enet_ring *ring, - struct sk_buff *skb, u32 l234info) +static bool hns3_checksum_complete(struct hns3_enet_ring *ring, + struct sk_buff *skb, u32 ptype, u16 csum) { - u32 lo, hi; + if (ptype == HNS3_INVALID_PTYPE || + hns3_rx_ptype_tbl[ptype].ip_summed != CHECKSUM_COMPLETE) + return false;
u64_stats_update_begin(&ring->syncp); ring->stats.csum_complete++; u64_stats_update_end(&ring->syncp); skb->ip_summed = CHECKSUM_COMPLETE; - lo = hnae3_get_field(l234info, HNS3_RXD_L2_CSUM_L_M, - HNS3_RXD_L2_CSUM_L_S); - hi = hnae3_get_field(l234info, HNS3_RXD_L2_CSUM_H_M, - HNS3_RXD_L2_CSUM_H_S); - skb->csum = csum_unfold((__force __sum16)(lo | hi << 8)); + skb->csum = csum_unfold((__force __sum16)csum); + + return true; }
static void hns3_rx_handle_csum(struct sk_buff *skb, u32 l234info, @@ -3303,7 +3303,8 @@ static void hns3_rx_handle_csum(struct sk_buff *skb, u32 l234info, }
static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, - u32 l234info, u32 bd_base_info, u32 ol_info) + u32 l234info, u32 bd_base_info, u32 ol_info, + u16 csum) { struct net_device *netdev = ring_to_netdev(ring); struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -3320,10 +3321,8 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M, HNS3_RXD_PTYPE_S);
- if (l234info & BIT(HNS3_RXD_L2_CSUM_B)) { - hns3_checksum_complete(ring, skb, l234info); + if (hns3_checksum_complete(ring, skb, ptype, csum)) return; - }
/* check if hardware has done checksum */ if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) @@ -3523,7 +3522,7 @@ static int hns3_add_frag(struct hns3_enet_ring *ring)
static int hns3_set_gro_and_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, u32 l234info, - u32 bd_base_info, u32 ol_info) + u32 bd_base_info, u32 ol_info, u16 csum) { struct net_device *netdev = ring_to_netdev(ring); struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -3534,7 +3533,8 @@ static int hns3_set_gro_and_checksum(struct hns3_enet_ring *ring, HNS3_RXD_GRO_SIZE_S); /* if there is no HW GRO, do not set gro params */ if (!skb_shinfo(skb)->gso_size) { - hns3_rx_checksum(ring, skb, l234info, bd_base_info, ol_info); + hns3_rx_checksum(ring, skb, l234info, bd_base_info, ol_info, + csum); return 0; }
@@ -3584,6 +3584,7 @@ static int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb) struct hns3_desc *desc; unsigned int len; int pre_ntc, ret; + u16 csum;
/* bdinfo handled below is only valid on the last BD of the * current packet, and ring->next_to_clean indicates the first @@ -3595,6 +3596,7 @@ static int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb) bd_base_info = le32_to_cpu(desc->rx.bd_base_info); l234info = le32_to_cpu(desc->rx.l234_info); ol_info = le32_to_cpu(desc->rx.ol_info); + csum = le16_to_cpu(desc->csum);
/* Based on hw strategy, the tag offloaded will be stored at * ot_vlan_tag in two layer tag case, and stored at vlan_tag @@ -3627,7 +3629,7 @@ static int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb)
/* This is needed in order to enable forwarding support */ ret = hns3_set_gro_and_checksum(ring, skb, l234info, - bd_base_info, ol_info); + bd_base_info, ol_info, csum); if (unlikely(ret)) { u64_stats_update_begin(&ring->syncp); ring->stats.rx_err_cnt++; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 843642b9884b..c9aebda26f6a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -83,12 +83,6 @@ enum hns3_nic_state { #define HNS3_RXD_STRP_TAGP_S 13 #define HNS3_RXD_STRP_TAGP_M (0x3 << HNS3_RXD_STRP_TAGP_S)
-#define HNS3_RXD_L2_CSUM_B 15 -#define HNS3_RXD_L2_CSUM_L_S 4 -#define HNS3_RXD_L2_CSUM_L_M (0xff << HNS3_RXD_L2_CSUM_L_S) -#define HNS3_RXD_L2_CSUM_H_S 24 -#define HNS3_RXD_L2_CSUM_H_M (0xff << HNS3_RXD_L2_CSUM_H_S) - #define HNS3_RXD_L2E_B 16 #define HNS3_RXD_L3E_B 17 #define HNS3_RXD_L4E_B 18 @@ -242,7 +236,10 @@ enum hns3_pkt_tun_type {
/* hardware spec ring buffer format */ struct __packed hns3_desc { - __le64 addr; + union { + __le64 addr; + __le16 csum; + }; union { struct { __le16 vlan_tag; @@ -409,6 +406,7 @@ struct ring_stats { u64 rx_multicast; u64 non_reuse_pg; }; + __le16 csum; }; };
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit 5e69ea7ee2a69f68c4172afcb0cbe29e7162fb6e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, each debugfs command needs to create a file to get the information. To better support more debugfs commands, the debugfs process is reconstructed, including the process of creating dentries and files, and obtaining information.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 13 +- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 193 +++++++++++++++--- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 29 +++ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 7 +- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 32 ++- .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 5 + .../hisilicon/hns3/hns3pf/hclge_main.h | 2 +- 8 files changed, 236 insertions(+), 47 deletions(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 87928f8d089c..c15eb5b06972 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -249,6 +249,13 @@ enum hnae3_port_base_vlan_state { HNAE3_PORT_BASE_VLAN_NOCHANGE, };
+enum hnae3_dbg_cmd { + HNAE3_DBG_CMD_TM_NODES, + HNAE3_DBG_CMD_TM_PRI, + HNAE3_DBG_CMD_TM_QSET, + HNAE3_DBG_CMD_UNKNOWN, +}; + struct hnae3_vector_info { u8 __iomem *io_addr; int vector; @@ -626,7 +633,7 @@ struct hnae3_ae_ops { int (*add_arfs_entry)(struct hnae3_handle *handle, u16 queue_id, u16 flow_id, struct flow_keys *fkeys); int (*dbg_run_cmd)(struct hnae3_handle *handle, const char *cmd_buf); - int (*dbg_read_cmd)(struct hnae3_handle *handle, const char *cmd_buf, + int (*dbg_read_cmd)(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len); pci_ers_result_t (*handle_hw_ras_error)(struct hnae3_ae_dev *ae_dev); bool (*get_hw_reset_stat)(struct hnae3_handle *handle); @@ -789,10 +796,6 @@ struct hnae3_handle { #define hnae3_get_bit(origin, shift) \ hnae3_get_field(origin, 0x1 << (shift), shift)
-#define HNAE3_DBG_TM_NODES "tm_nodes" -#define HNAE3_DBG_TM_PRI "tm_priority" -#define HNAE3_DBG_TM_QSET "tm_qset" - int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev); void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index e405fef81d15..62a05955fda2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -5,13 +5,48 @@ #include <linux/device.h>
#include "hnae3.h" +#include "hns3_debugfs.h" #include "hns3_enet.h"
-#define HNS3_DBG_READ_LEN 65536 -#define HNS3_DBG_WRITE_LEN 1024 - static struct dentry *hns3_dbgfs_root;
+static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { + { + .name = "tm" + }, + /* keep common at the bottom and add new directory above */ + { + .name = "common" + }, +}; + +static int hns3_dbg_common_file_init(struct hnae3_handle *handle, + unsigned int cmd); + +static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { + { + .name = "tm_nodes", + .cmd = HNAE3_DBG_CMD_TM_NODES, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "tm_priority", + .cmd = HNAE3_DBG_CMD_TM_PRI, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "tm_qset", + .cmd = HNAE3_DBG_CMD_TM_QSET, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, +}; + static int hns3_dbg_queue_info(struct hnae3_handle *h, const char *cmd_buf) { @@ -493,37 +528,90 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, return count; }
+static int hns3_dbg_get_cmd_index(struct hnae3_handle *handle, + const unsigned char *name, u32 *index) +{ + u32 i; + + for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { + if (!strncmp(name, hns3_dbg_cmd[i].name, + strlen(hns3_dbg_cmd[i].name))) { + *index = i; + return 0; + } + } + + dev_err(&handle->pdev->dev, "unknown command(%s)\n", name); + return -EINVAL; +} + +static int hns3_dbg_read_cmd(struct hnae3_handle *handle, + enum hnae3_dbg_cmd cmd, char *buf, int len) +{ + const struct hnae3_ae_ops *ops = handle->ae_algo->ops; + + if (!ops->dbg_read_cmd) + return -EOPNOTSUPP; + + return ops->dbg_read_cmd(handle, cmd, buf, len); +} + static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { struct hnae3_handle *handle = filp->private_data; - const struct hnae3_ae_ops *ops = handle->ae_algo->ops; struct hns3_nic_priv *priv = handle->priv; - char *cmd_buf, *read_buf; ssize_t size = 0; - int ret = 0; - - read_buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); - if (!read_buf) - return -ENOMEM; + char **save_buf; + char *read_buf; + u32 index; + int ret;
- cmd_buf = filp->f_path.dentry->d_iname; + ret = hns3_dbg_get_cmd_index(handle, filp->f_path.dentry->d_iname, + &index); + if (ret) + return ret;
- if (ops->dbg_read_cmd) - ret = ops->dbg_read_cmd(handle, cmd_buf, read_buf, - HNS3_DBG_READ_LEN); + save_buf = &hns3_dbg_cmd[index].buf;
- if (ret) { - dev_info(priv->dev, "unknown command\n"); + if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || + test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) { + ret = -EBUSY; goto out; }
+ if (*save_buf) { + read_buf = *save_buf; + } else { + read_buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL); + if (!read_buf) + return -ENOMEM; + + /* save the buffer addr until the last read operation */ + *save_buf = read_buf; + } + + /* get data ready for the first time to read */ + if (!*ppos) { + ret = hns3_dbg_read_cmd(handle, hns3_dbg_cmd[index].cmd, + read_buf, hns3_dbg_cmd[index].buf_len); + if (ret) + goto out; + } + size = simple_read_from_buffer(buffer, count, ppos, read_buf, strlen(read_buf)); + if (size > 0) + return size;
out: - kfree(read_buf); - return size; + /* free the buffer for the last read operation */ + if (*save_buf) { + kvfree(*save_buf); + *save_buf = NULL; + } + + return ret; }
static const struct file_operations hns3_dbg_cmd_fops = { @@ -539,29 +627,76 @@ static const struct file_operations hns3_dbg_fops = { .read = hns3_dbg_read, };
-void hns3_dbg_init(struct hnae3_handle *handle) +static int +hns3_dbg_common_file_init(struct hnae3_handle *handle, u32 cmd) +{ + struct dentry *entry_dir; + + entry_dir = hns3_dbg_dentry[hns3_dbg_cmd[cmd].dentry].dentry; + debugfs_create_file(hns3_dbg_cmd[cmd].name, 0400, entry_dir, + handle, &hns3_dbg_fops); + + return 0; +} + +int hns3_dbg_init(struct hnae3_handle *handle) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev); const char *name = pci_name(handle->pdev); - struct dentry *entry_dir; + int ret; + u32 i;
- handle->hnae3_dbgfs = debugfs_create_dir(name, hns3_dbgfs_root); + hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry = + debugfs_create_dir(name, hns3_dbgfs_root); + handle->hnae3_dbgfs = hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry;
debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, &hns3_dbg_cmd_fops);
- entry_dir = debugfs_create_dir("tm", handle->hnae3_dbgfs); - if (ae_dev->dev_version > HNAE3_DEVICE_VERSION_V2) - debugfs_create_file(HNAE3_DBG_TM_NODES, 0600, entry_dir, handle, - &hns3_dbg_fops); - debugfs_create_file(HNAE3_DBG_TM_PRI, 0600, entry_dir, handle, - &hns3_dbg_fops); - debugfs_create_file(HNAE3_DBG_TM_QSET, 0600, entry_dir, handle, - &hns3_dbg_fops); + for (i = 0; i < HNS3_DBG_DENTRY_COMMON; i++) + hns3_dbg_dentry[i].dentry = + debugfs_create_dir(hns3_dbg_dentry[i].name, + handle->hnae3_dbgfs); + + for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { + if (hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES && + ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) + continue; + + if (!hns3_dbg_cmd[i].init) { + dev_err(&handle->pdev->dev, + "cmd %s lack of init func\n", + hns3_dbg_cmd[i].name); + ret = -EINVAL; + goto out; + } + + ret = hns3_dbg_cmd[i].init(handle, i); + if (ret) { + dev_err(&handle->pdev->dev, "failed to init cmd %s\n", + hns3_dbg_cmd[i].name); + goto out; + } + } + + return 0; + +out: + debugfs_remove_recursive(handle->hnae3_dbgfs); + handle->hnae3_dbgfs = NULL; + return ret; }
void hns3_dbg_uninit(struct hnae3_handle *handle) { + u32 i; + + for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) + if (hns3_dbg_cmd[i].buf) { + kvfree(hns3_dbg_cmd[i].buf); + hns3_dbg_cmd[i].buf = NULL; + } + debugfs_remove_recursive(handle->hnae3_dbgfs); handle->hnae3_dbgfs = NULL; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h new file mode 100644 index 000000000000..1648f686114e --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2021 Hisilicon Limited. */ + +#ifndef __HNS3_DEBUGFS_H +#define __HNS3_DEBUGFS_H + +#define HNS3_DBG_READ_LEN 65536 +#define HNS3_DBG_WRITE_LEN 1024 + +enum hns3_dbg_dentry_type { + HNS3_DBG_DENTRY_TM, + HNS3_DBG_DENTRY_COMMON, +}; + +struct hns3_dbg_dentry_info { + const char *name; + struct dentry *dentry; +}; + +struct hns3_dbg_cmd_info { + const char *name; + enum hnae3_dbg_cmd cmd; + enum hns3_dbg_dentry_type dentry; + u32 buf_len; + char *buf; + int (*init)(struct hnae3_handle *handle, unsigned int cmd); +}; + +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0899d21eea33..77ec11f7ce25 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4638,7 +4638,12 @@ static int hns3_client_init(struct hnae3_handle *handle)
hns3_dcbnl_setup(handle);
- hns3_dbg_init(handle); + ret = hns3_dbg_init(handle); + if (ret) { + dev_err(priv->dev, "failed to init debugfs, ret = %d\n", + ret); + goto out_client_start; + }
netdev->max_mtu = HNS3_MAX_MTU(ae_dev->dev_specs.max_frm_size);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index c9aebda26f6a..5c72f41cf57e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -650,7 +650,7 @@ void hns3_dcbnl_setup(struct hnae3_handle *handle); static inline void hns3_dcbnl_setup(struct hnae3_handle *handle) {} #endif
-void hns3_dbg_init(struct hnae3_handle *handle); +int hns3_dbg_init(struct hnae3_handle *handle); void hns3_dbg_uninit(struct hnae3_handle *handle); void hns3_dbg_register_debugfs(const char *debugfs_dir_name); void hns3_dbg_unregister_debugfs(void); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 85d306459e36..7f1abdff25b0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1800,21 +1800,33 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) return 0; }
-int hclge_dbg_read_cmd(struct hnae3_handle *handle, const char *cmd_buf, +static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { + { + .cmd = HNAE3_DBG_CMD_TM_NODES, + .dbg_dump = hclge_dbg_dump_tm_nodes, + }, + { + .cmd = HNAE3_DBG_CMD_TM_PRI, + .dbg_dump = hclge_dbg_dump_tm_pri, + }, + { + .cmd = HNAE3_DBG_CMD_TM_QSET, + .dbg_dump = hclge_dbg_dump_tm_qset, + }, +}; + +int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + u32 i;
- if (strncmp(cmd_buf, HNAE3_DBG_TM_NODES, - strlen(HNAE3_DBG_TM_NODES)) == 0) - return hclge_dbg_dump_tm_nodes(hdev, buf, len); - else if (strncmp(cmd_buf, HNAE3_DBG_TM_PRI, - strlen(HNAE3_DBG_TM_PRI)) == 0) - return hclge_dbg_dump_tm_pri(hdev, buf, len); - else if (strncmp(cmd_buf, HNAE3_DBG_TM_QSET, - strlen(HNAE3_DBG_TM_QSET)) == 0) - return hclge_dbg_dump_tm_qset(hdev, buf, len); + for (i = 0; i < ARRAY_SIZE(hclge_dbg_cmd_func); i++) { + if (cmd == hclge_dbg_cmd_func[i].cmd) + return hclge_dbg_cmd_func[i].dbg_dump(hdev, buf, len); + }
+ dev_err(&hdev->pdev->dev, "invalid command(%d)\n", cmd); return -EINVAL; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index ca2ab6cf84d9..0c144532e6ad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -83,6 +83,11 @@ struct hclge_dbg_reg_type_info { struct hclge_dbg_reg_common_msg reg_msg; };
+struct hclge_dbg_func { + enum hnae3_dbg_cmd cmd; + int (*dbg_dump)(struct hclge_dev *hdev, char *buf, int len); +}; + static const struct hclge_dbg_dfx_message hclge_dbg_bios_common_reg[] = { {false, "Reserved"}, {true, "BP_CPU_STATE"}, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 10f5c11e6b66..9e17c02de403 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1061,7 +1061,7 @@ int hclge_vport_start(struct hclge_vport *vport); void hclge_vport_stop(struct hclge_vport *vport); int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu); int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf); -int hclge_dbg_read_cmd(struct hnae3_handle *handle, const char *cmd_buf, +int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len); u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id); int hclge_notify_client(struct hclge_dev *hdev,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit c929bc2ac36efa9344e6c8b8f55f6b8eeebb4393 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for dev capability and dev spec are implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "dev_info" for them, and query them by command "cat dev_info", return the result to userspace, rather than record in dmesg.
The display style is below: $cat dev_info dev capability: support FD: yes support GRO: yes support FEC: yes support UDP GSO: no support PTP: no support INT QL: no support HW TX csum: no support UDP tunnel csum: no support TX push: no support imp-controlled PHY: no support rxd advanced layout: no
dev spec: MAC entry num: 0 MNG entry num: 0 MAX non tso bd num: 8 RSS ind tbl size: 512 RSS key size: 40 RSS size: 1 Allocated RSS size: 0 Task queue pairs numbers: 1 RX buffer length: 2048 Desc num per TX queue: 1024 Desc num per RX queue: 1024 Total number of enabled TCs: 1 MAX INT QL: 0 MAX INT GL: 8160 MAX TM RATE: 100000 MAX QSET number: 1024
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 181 ++++++++++++------ .../ethernet/hisilicon/hns3/hns3_debugfs.h | 10 + 3 files changed, 132 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c15eb5b06972..0a16d19a971a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -253,6 +253,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_NODES, HNAE3_DBG_CMD_TM_PRI, HNAE3_DBG_CMD_TM_QSET, + HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 62a05955fda2..e6c3175bca4d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -45,6 +45,50 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "dev_info", + .cmd = HNAE3_DBG_CMD_DEV_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, +}; + +static struct hns3_dbg_cap_info hns3_dbg_cap[] = { + { + .name = "support FD", + .cap_bit = HNAE3_DEV_SUPPORT_FD_B, + }, { + .name = "support GRO", + .cap_bit = HNAE3_DEV_SUPPORT_GRO_B, + }, { + .name = "support FEC", + .cap_bit = HNAE3_DEV_SUPPORT_FEC_B, + }, { + .name = "support UDP GSO", + .cap_bit = HNAE3_DEV_SUPPORT_UDP_GSO_B, + }, { + .name = "support PTP", + .cap_bit = HNAE3_DEV_SUPPORT_PTP_B, + }, { + .name = "support INT QL", + .cap_bit = HNAE3_DEV_SUPPORT_INT_QL_B, + }, { + .name = "support HW TX csum", + .cap_bit = HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, + }, { + .name = "support UDP tunnel csum", + .cap_bit = HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, + }, { + .name = "support TX push", + .cap_bit = HNAE3_DEV_SUPPORT_TX_PUSH_B, + }, { + .name = "support imp-controlled PHY", + .cap_bit = HNAE3_DEV_SUPPORT_PHY_IMP_B, + }, { + .name = "support rxd advanced layout", + .cap_bit = HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, + }, };
static int hns3_dbg_queue_info(struct hnae3_handle *h, @@ -320,8 +364,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "queue info <number>\n"); dev_info(&h->pdev->dev, "queue map\n"); dev_info(&h->pdev->dev, "bd info <q_num> <bd index>\n"); - dev_info(&h->pdev->dev, "dev capability\n"); - dev_info(&h->pdev->dev, "dev spec\n");
if (!hns3_is_phys_func(h->pdev)) return; @@ -363,68 +405,78 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "%s", printf_buf); }
-static void hns3_dbg_dev_caps(struct hnae3_handle *h) +static void +hns3_dbg_dev_caps(struct hnae3_handle *h, char *buf, int len, int *pos) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); - unsigned long *caps; - - caps = ae_dev->caps; - - dev_info(&h->pdev->dev, "support FD: %s\n", - test_bit(HNAE3_DEV_SUPPORT_FD_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support GRO: %s\n", - test_bit(HNAE3_DEV_SUPPORT_GRO_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support FEC: %s\n", - test_bit(HNAE3_DEV_SUPPORT_FEC_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support UDP GSO: %s\n", - test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support PTP: %s\n", - test_bit(HNAE3_DEV_SUPPORT_PTP_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support INT QL: %s\n", - test_bit(HNAE3_DEV_SUPPORT_INT_QL_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support HW TX csum: %s\n", - test_bit(HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support UDP tunnel csum: %s\n", - test_bit(HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, caps) ? - "yes" : "no"); - dev_info(&h->pdev->dev, "support PAUSE: %s\n", - test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps) ? - "yes" : "no"); - dev_info(&h->pdev->dev, "support imp-controlled PHY: %s\n", - test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, caps) ? "yes" : "no"); - dev_info(&h->pdev->dev, "support rxd advanced layout: %s\n", - test_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, caps) ? - "yes" : "no"); + static const char * const str[] = {"no", "yes"}; + unsigned long *caps = ae_dev->caps; + u32 i, state; + + *pos += scnprintf(buf + *pos, len - *pos, "dev capability:\n"); + + for (i = 0; i < ARRAY_SIZE(hns3_dbg_cap); i++) { + state = test_bit(hns3_dbg_cap[i].cap_bit, caps); + *pos += scnprintf(buf + *pos, len - *pos, "%s: %s\n", + hns3_dbg_cap[i].name, str[state]); + } + + *pos += scnprintf(buf + *pos, len - *pos, "\n"); }
-static void hns3_dbg_dev_specs(struct hnae3_handle *h) +static void +hns3_dbg_dev_specs(struct hnae3_handle *h, char *buf, int len, int *pos) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); struct hnae3_dev_specs *dev_specs = &ae_dev->dev_specs; struct hnae3_knic_private_info *kinfo = &h->kinfo; - struct hns3_nic_priv *priv = h->priv; - - dev_info(priv->dev, "MAC entry num: %u\n", dev_specs->mac_entry_num); - dev_info(priv->dev, "MNG entry num: %u\n", dev_specs->mng_entry_num); - dev_info(priv->dev, "MAX non tso bd num: %u\n", - dev_specs->max_non_tso_bd_num); - dev_info(priv->dev, "RSS ind tbl size: %u\n", - dev_specs->rss_ind_tbl_size); - dev_info(priv->dev, "RSS key size: %u\n", dev_specs->rss_key_size); - dev_info(priv->dev, "RSS size: %u\n", kinfo->rss_size); - dev_info(priv->dev, "Allocated RSS size: %u\n", kinfo->req_rss_size); - dev_info(priv->dev, "Task queue pairs numbers: %u\n", kinfo->num_tqps); - - dev_info(priv->dev, "RX buffer length: %u\n", kinfo->rx_buf_len); - dev_info(priv->dev, "Desc num per TX queue: %u\n", kinfo->num_tx_desc); - dev_info(priv->dev, "Desc num per RX queue: %u\n", kinfo->num_rx_desc); - dev_info(priv->dev, "Total number of enabled TCs: %u\n", - kinfo->tc_info.num_tc); - dev_info(priv->dev, "MAX INT QL: %u\n", dev_specs->int_ql_max); - dev_info(priv->dev, "MAX INT GL: %u\n", dev_specs->max_int_gl); - dev_info(priv->dev, "MAX frame size: %u\n", dev_specs->max_frm_size); - dev_info(priv->dev, "MAX TM RATE: %uMbps\n", dev_specs->max_tm_rate); - dev_info(priv->dev, "MAX QSET number: %u\n", dev_specs->max_qset_num); + + *pos += scnprintf(buf + *pos, len - *pos, "dev_spec:\n"); + *pos += scnprintf(buf + *pos, len - *pos, "MAC entry num: %u\n", + dev_specs->mac_entry_num); + *pos += scnprintf(buf + *pos, len - *pos, "MNG entry num: %u\n", + dev_specs->mng_entry_num); + *pos += scnprintf(buf + *pos, len - *pos, "MAX non tso bd num: %u\n", + dev_specs->max_non_tso_bd_num); + *pos += scnprintf(buf + *pos, len - *pos, "RSS ind tbl size: %u\n", + dev_specs->rss_ind_tbl_size); + *pos += scnprintf(buf + *pos, len - *pos, "RSS key size: %u\n", + dev_specs->rss_key_size); + *pos += scnprintf(buf + *pos, len - *pos, "RSS size: %u\n", + kinfo->rss_size); + *pos += scnprintf(buf + *pos, len - *pos, "Allocated RSS size: %u\n", + kinfo->req_rss_size); + *pos += scnprintf(buf + *pos, len - *pos, + "Task queue pairs numbers: %u\n", + kinfo->num_tqps); + *pos += scnprintf(buf + *pos, len - *pos, "RX buffer length: %u\n", + kinfo->rx_buf_len); + *pos += scnprintf(buf + *pos, len - *pos, "Desc num per TX queue: %u\n", + kinfo->num_tx_desc); + *pos += scnprintf(buf + *pos, len - *pos, "Desc num per RX queue: %u\n", + kinfo->num_rx_desc); + *pos += scnprintf(buf + *pos, len - *pos, + "Total number of enabled TCs: %u\n", + kinfo->tc_info.num_tc); + *pos += scnprintf(buf + *pos, len - *pos, "MAX INT QL: %u\n", + dev_specs->int_ql_max); + *pos += scnprintf(buf + *pos, len - *pos, "MAX INT GL: %u\n", + dev_specs->max_int_gl); + *pos += scnprintf(buf + *pos, len - *pos, "MAX TM RATE: %u\n", + dev_specs->max_tm_rate); + *pos += scnprintf(buf + *pos, len - *pos, "MAX QSET number: %u\n", + dev_specs->max_qset_num); +} + +static int hns3_dbg_dev_info(struct hnae3_handle *h, char *buf, int len) +{ + int pos = 0; + + hns3_dbg_dev_caps(h, buf, len, &pos); + + hns3_dbg_dev_specs(h, buf, len, &pos); + + return 0; }
static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, @@ -468,10 +520,6 @@ static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf) ret = hns3_dbg_queue_map(handle); else if (strncmp(cmd_buf, "bd info", 7) == 0) ret = hns3_dbg_bd_info(handle, cmd_buf); - else if (strncmp(cmd_buf, "dev capability", 14) == 0) - hns3_dbg_dev_caps(handle); - else if (strncmp(cmd_buf, "dev spec", 8) == 0) - hns3_dbg_dev_specs(handle); else if (handle->ae_algo->ops->dbg_run_cmd) ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); else @@ -545,10 +593,23 @@ static int hns3_dbg_get_cmd_index(struct hnae3_handle *handle, return -EINVAL; }
+static const struct hns3_dbg_func hns3_dbg_cmd_func[] = { + { + .cmd = HNAE3_DBG_CMD_DEV_INFO, + .dbg_dump = hns3_dbg_dev_info, + }, +}; + static int hns3_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len) { const struct hnae3_ae_ops *ops = handle->ae_algo->ops; + u32 i; + + for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd_func); i++) { + if (cmd == hns3_dbg_cmd_func[i].cmd) + return hns3_dbg_cmd_func[i].dbg_dump(handle, buf, len); + }
if (!ops->dbg_read_cmd) return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index 1648f686114e..d16ec876bc71 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -26,4 +26,14 @@ struct hns3_dbg_cmd_info { int (*init)(struct hnae3_handle *handle, unsigned int cmd); };
+struct hns3_dbg_func { + enum hnae3_dbg_cmd cmd; + int (*dbg_dump)(struct hnae3_handle *handle, char *buf, int len); +}; + +struct hns3_dbg_cap_info { + const char *name; + enum HNAE3_DEV_CAP_BITS cap_bit; +}; + #endif
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 77e9184869c9fb00a482357ea8eef3bd7ae3d45a category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for bd info is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy.
To improve it, add two debugfs directories "tx_bd_info" and "rx_bd_info", and create a file for each queue under these two directories, and query the bd info of specific queue by "cat tx_bd_info/tx_bd_queue*" or "cat rx_bd_info/rx_bd_queue*", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat rx_bd_info/rx_bd_queue0 Queue 0 rx bd info: BD_IDX L234_INFO PKT_LEN SIZE... 0 0x0 60 60... 1 0x0 1512 1512...
$ cat tx_bd_info/tx_bd_queue0 Queue 0 tx bd info: BD_IDX ADDRESS VLAN_TAG SIZE... 0 0x0 0 0... 1 0x0 0 0...
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 340 ++++++++++++------ .../ethernet/hisilicon/hns3/hns3_debugfs.h | 19 + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 1 + 5 files changed, 263 insertions(+), 101 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 0a16d19a971a..5b030e92b56c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -254,6 +254,8 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_PRI, HNAE3_DBG_CMD_TM_QSET, HNAE3_DBG_CMD_DEV_INFO, + HNAE3_DBG_CMD_TX_BD, + HNAE3_DBG_CMD_RX_BD, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index e6c3175bca4d..fb3c2d4fbcc5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -14,12 +14,19 @@ static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { { .name = "tm" }, + { + .name = "tx_bd_info" + }, + { + .name = "rx_bd_info" + }, /* keep common at the bottom and add new directory above */ { .name = "common" }, };
+static int hns3_dbg_bd_file_init(struct hnae3_handle *handle, unsigned int cmd); static int hns3_dbg_common_file_init(struct hnae3_handle *handle, unsigned int cmd);
@@ -52,6 +59,20 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "tx_bd_queue", + .cmd = HNAE3_DBG_CMD_TX_BD, + .dentry = HNS3_DBG_DENTRY_TX_BD, + .buf_len = HNS3_DBG_READ_LEN_4MB, + .init = hns3_dbg_bd_file_init, + }, + { + .name = "rx_bd_queue", + .cmd = HNAE3_DBG_CMD_RX_BD, + .dentry = HNS3_DBG_DENTRY_RX_BD, + .buf_len = HNS3_DBG_READ_LEN_4MB, + .init = hns3_dbg_bd_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -91,6 +112,27 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { }, };
+static void hns3_dbg_fill_content(char *content, u16 len, + const struct hns3_dbg_item *items, + const char **result, u16 size) +{ + char *pos = content; + u16 i; + + memset(content, ' ', len); + for (i = 0; i < size; i++) { + if (result) + strncpy(pos, result[i], strlen(result[i])); + else + strncpy(pos, items[i].name, strlen(items[i].name)); + + pos += strlen(items[i].name) + items[i].interval; + } + + *pos++ = '\n'; + *pos++ = '\0'; +} + static int hns3_dbg_queue_info(struct hnae3_handle *h, const char *cmd_buf) { @@ -248,108 +290,159 @@ static int hns3_dbg_queue_map(struct hnae3_handle *h) return 0; }
-static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf) +static const struct hns3_dbg_item rx_bd_info_items[] = { + { "BD_IDX", 3 }, + { "L234_INFO", 2 }, + { "PKT_LEN", 3 }, + { "SIZE", 4 }, + { "RSS_HASH", 4 }, + { "FD_ID", 2 }, + { "VLAN_TAG", 2 }, + { "O_DM_VLAN_ID_FB", 2 }, + { "OT_VLAN_TAG", 2 }, + { "BD_BASE_INFO", 2 }, + { "PTYPE", 2 }, + { "HW_CSUM", 2 }, +}; + +static void hns3_dump_rx_bd_info(struct hns3_nic_priv *priv, + struct hns3_desc *desc, char **result, int idx) { - struct hns3_nic_priv *priv = h->priv; - struct hns3_desc *rx_desc, *tx_desc; - struct device *dev = &h->pdev->dev; + unsigned int j = 0; + + sprintf(result[j++], "%5d", idx); + sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.l234_info)); + sprintf(result[j++], "%7u", le16_to_cpu(desc->rx.pkt_len)); + sprintf(result[j++], "%4u", le16_to_cpu(desc->rx.size)); + sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.rss_hash)); + sprintf(result[j++], "%5u", le16_to_cpu(desc->rx.fd_id)); + sprintf(result[j++], "%8u", le16_to_cpu(desc->rx.vlan_tag)); + sprintf(result[j++], "%15u", le16_to_cpu(desc->rx.o_dm_vlan_id_fb)); + sprintf(result[j++], "%11u", le16_to_cpu(desc->rx.ot_vlan_tag)); + sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.bd_base_info)); + if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) { + u32 ol_info = le32_to_cpu(desc->rx.ol_info); + + sprintf(result[j++], "%5lu", hnae3_get_field(ol_info, + HNS3_RXD_PTYPE_M, + HNS3_RXD_PTYPE_S)); + sprintf(result[j++], "%7u", le16_to_cpu(desc->csum)); + } else { + sprintf(result[j++], "NA"); + sprintf(result[j++], "NA"); + } +} + +static int hns3_dbg_rx_bd_info(struct hns3_dbg_data *d, char *buf, int len) +{ + char data_str[ARRAY_SIZE(rx_bd_info_items)][HNS3_DBG_DATA_STR_LEN]; + struct hns3_nic_priv *priv = d->handle->priv; + char *result[ARRAY_SIZE(rx_bd_info_items)]; + char content[HNS3_DBG_INFO_LEN]; struct hns3_enet_ring *ring; - u32 tx_index, rx_index; - u32 q_num, value; - dma_addr_t addr; - u16 mss_hw_csum; - u32 l234info; - int cnt; + struct hns3_desc *desc; + unsigned int i; + int pos = 0;
- cnt = sscanf(&cmd_buf[8], "%u %u", &q_num, &tx_index); - if (cnt == 2) { - rx_index = tx_index; - } else if (cnt != 1) { - dev_err(dev, "bd info: bad command string, cnt=%d\n", cnt); + if (d->qid >= d->handle->kinfo.num_tqps) { + dev_err(&d->handle->pdev->dev, + "queue%u is not in use\n", d->qid); return -EINVAL; }
- if (q_num >= h->kinfo.num_tqps) { - dev_err(dev, "Queue number(%u) is out of range(0-%u)\n", q_num, - h->kinfo.num_tqps - 1); - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(rx_bd_info_items); i++) + result[i] = &data_str[i][0]; + + pos += scnprintf(buf + pos, len - pos, + "Queue %u rx bd info:\n", d->qid); + hns3_dbg_fill_content(content, sizeof(content), rx_bd_info_items, + NULL, ARRAY_SIZE(rx_bd_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + + ring = &priv->ring[d->qid + d->handle->kinfo.num_tqps]; + for (i = 0; i < ring->desc_num; i++) { + desc = &ring->desc[i]; + + hns3_dump_rx_bd_info(priv, desc, result, i); + hns3_dbg_fill_content(content, sizeof(content), + rx_bd_info_items, (const char **)result, + ARRAY_SIZE(rx_bd_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); }
- ring = &priv->ring[q_num]; - value = readl_relaxed(ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG); - tx_index = (cnt == 1) ? value : tx_index; + return 0; +} + +static const struct hns3_dbg_item tx_bd_info_items[] = { + { "BD_IDX", 5 }, + { "ADDRESS", 2 }, + { "VLAN_TAG", 2 }, + { "SIZE", 2 }, + { "T_CS_VLAN_TSO", 2 }, + { "OT_VLAN_TAG", 3 }, + { "TV", 2 }, + { "OLT_VLAN_LEN", 2}, + { "PAYLEN_OL4CS", 2}, + { "BD_FE_SC_VLD", 2}, + { "MSS_HW_CSUM", 0}, +};
- if (tx_index >= ring->desc_num) { - dev_err(dev, "bd index(%u) is out of range(0-%u)\n", tx_index, - ring->desc_num - 1); +static void hns3_dump_tx_bd_info(struct hns3_nic_priv *priv, + struct hns3_desc *desc, char **result, int idx) +{ + unsigned int j = 0; + + sprintf(result[j++], "%6d", idx); + sprintf(result[j++], "%#llx", le64_to_cpu(desc->addr)); + sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.vlan_tag)); + sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.send_size)); + sprintf(result[j++], "%#x", + le32_to_cpu(desc->tx.type_cs_vlan_tso_len)); + sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.outer_vlan_tag)); + sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.tv)); + sprintf(result[j++], "%10u", + le32_to_cpu(desc->tx.ol_type_vlan_len_msec)); + sprintf(result[j++], "%#x", le32_to_cpu(desc->tx.paylen_ol4cs)); + sprintf(result[j++], "%#x", le16_to_cpu(desc->tx.bdtp_fe_sc_vld_ra_ri)); + sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.mss_hw_csum)); +} + +static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) +{ + char data_str[ARRAY_SIZE(tx_bd_info_items)][HNS3_DBG_DATA_STR_LEN]; + struct hns3_nic_priv *priv = d->handle->priv; + char *result[ARRAY_SIZE(tx_bd_info_items)]; + char content[HNS3_DBG_INFO_LEN]; + struct hns3_enet_ring *ring; + struct hns3_desc *desc; + unsigned int i; + int pos = 0; + + if (d->qid >= d->handle->kinfo.num_tqps) { + dev_err(&d->handle->pdev->dev, + "queue%u is not in use\n", d->qid); return -EINVAL; }
- tx_desc = &ring->desc[tx_index]; - addr = le64_to_cpu(tx_desc->addr); - mss_hw_csum = le16_to_cpu(tx_desc->tx.mss_hw_csum); - dev_info(dev, "TX Queue Num: %u, BD Index: %u\n", q_num, tx_index); - dev_info(dev, "(TX)addr: %pad\n", &addr); - dev_info(dev, "(TX)vlan_tag: %u\n", le16_to_cpu(tx_desc->tx.vlan_tag)); - dev_info(dev, "(TX)send_size: %u\n", - le16_to_cpu(tx_desc->tx.send_size)); - - if (mss_hw_csum & BIT(HNS3_TXD_HW_CS_B)) { - u32 offset = le32_to_cpu(tx_desc->tx.ol_type_vlan_len_msec); - u32 start = le32_to_cpu(tx_desc->tx.type_cs_vlan_tso_len); - - dev_info(dev, "(TX)csum start: %u\n", - hnae3_get_field(start, - HNS3_TXD_CSUM_START_M, - HNS3_TXD_CSUM_START_S)); - dev_info(dev, "(TX)csum offset: %u\n", - hnae3_get_field(offset, - HNS3_TXD_CSUM_OFFSET_M, - HNS3_TXD_CSUM_OFFSET_S)); - } else { - dev_info(dev, "(TX)vlan_tso: %u\n", - tx_desc->tx.type_cs_vlan_tso); - dev_info(dev, "(TX)l2_len: %u\n", tx_desc->tx.l2_len); - dev_info(dev, "(TX)l3_len: %u\n", tx_desc->tx.l3_len); - dev_info(dev, "(TX)l4_len: %u\n", tx_desc->tx.l4_len); - dev_info(dev, "(TX)vlan_msec: %u\n", - tx_desc->tx.ol_type_vlan_msec); - dev_info(dev, "(TX)ol2_len: %u\n", tx_desc->tx.ol2_len); - dev_info(dev, "(TX)ol3_len: %u\n", tx_desc->tx.ol3_len); - dev_info(dev, "(TX)ol4_len: %u\n", tx_desc->tx.ol4_len); - } + for (i = 0; i < ARRAY_SIZE(tx_bd_info_items); i++) + result[i] = &data_str[i][0]; + + pos += scnprintf(buf + pos, len - pos, + "Queue %u tx bd info:\n", d->qid); + hns3_dbg_fill_content(content, sizeof(content), tx_bd_info_items, + NULL, ARRAY_SIZE(tx_bd_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content);
- dev_info(dev, "(TX)vlan_tag: %u\n", - le16_to_cpu(tx_desc->tx.outer_vlan_tag)); - dev_info(dev, "(TX)tv: %u\n", le16_to_cpu(tx_desc->tx.tv)); - dev_info(dev, "(TX)paylen_ol4cs: %u\n", - le32_to_cpu(tx_desc->tx.paylen_ol4cs)); - dev_info(dev, "(TX)vld_ra_ri: %u\n", - le16_to_cpu(tx_desc->tx.bdtp_fe_sc_vld_ra_ri)); - dev_info(dev, "(TX)mss_hw_csum: %u\n", mss_hw_csum); - - ring = &priv->ring[q_num + h->kinfo.num_tqps]; - value = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_TAIL_REG); - rx_index = (cnt == 1) ? value : tx_index; - rx_desc = &ring->desc[rx_index]; - - addr = le64_to_cpu(rx_desc->addr); - l234info = le32_to_cpu(rx_desc->rx.l234_info); - dev_info(dev, "RX Queue Num: %u, BD Index: %u\n", q_num, rx_index); - dev_info(dev, "(RX)addr: %pad\n", &addr); - dev_info(dev, "(RX)l234_info: %u\n", l234info); - - dev_info(dev, "(RX)pkt_len: %u\n", le16_to_cpu(rx_desc->rx.pkt_len)); - dev_info(dev, "(RX)size: %u\n", le16_to_cpu(rx_desc->rx.size)); - dev_info(dev, "(RX)rss_hash: %u\n", le32_to_cpu(rx_desc->rx.rss_hash)); - dev_info(dev, "(RX)fd_id: %u\n", le16_to_cpu(rx_desc->rx.fd_id)); - dev_info(dev, "(RX)vlan_tag: %u\n", le16_to_cpu(rx_desc->rx.vlan_tag)); - dev_info(dev, "(RX)o_dm_vlan_id_fb: %u\n", - le16_to_cpu(rx_desc->rx.o_dm_vlan_id_fb)); - dev_info(dev, "(RX)ot_vlan_tag: %u\n", - le16_to_cpu(rx_desc->rx.ot_vlan_tag)); - dev_info(dev, "(RX)bd_base_info: %u\n", - le32_to_cpu(rx_desc->rx.bd_base_info)); + ring = &priv->ring[d->qid]; + for (i = 0; i < ring->desc_num; i++) { + desc = &ring->desc[i]; + + hns3_dump_tx_bd_info(priv, desc, result, i); + hns3_dbg_fill_content(content, sizeof(content), + tx_bd_info_items, (const char **)result, + ARRAY_SIZE(tx_bd_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + }
return 0; } @@ -363,7 +456,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "available commands\n"); dev_info(&h->pdev->dev, "queue info <number>\n"); dev_info(&h->pdev->dev, "queue map\n"); - dev_info(&h->pdev->dev, "bd info <q_num> <bd index>\n");
if (!hns3_is_phys_func(h->pdev)) return; @@ -518,8 +610,6 @@ static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf) ret = hns3_dbg_queue_info(handle, cmd_buf); else if (strncmp(cmd_buf, "queue map", 9) == 0) ret = hns3_dbg_queue_map(handle); - else if (strncmp(cmd_buf, "bd info", 7) == 0) - ret = hns3_dbg_bd_info(handle, cmd_buf); else if (handle->ae_algo->ops->dbg_run_cmd) ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); else @@ -598,29 +688,46 @@ static const struct hns3_dbg_func hns3_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_DEV_INFO, .dbg_dump = hns3_dbg_dev_info, }, + { + .cmd = HNAE3_DBG_CMD_TX_BD, + .dbg_dump_bd = hns3_dbg_tx_bd_info, + }, + { + .cmd = HNAE3_DBG_CMD_RX_BD, + .dbg_dump_bd = hns3_dbg_rx_bd_info, + }, };
-static int hns3_dbg_read_cmd(struct hnae3_handle *handle, +static int hns3_dbg_read_cmd(struct hns3_dbg_data *dbg_data, enum hnae3_dbg_cmd cmd, char *buf, int len) { - const struct hnae3_ae_ops *ops = handle->ae_algo->ops; + const struct hnae3_ae_ops *ops = dbg_data->handle->ae_algo->ops; + const struct hns3_dbg_func *cmd_func; u32 i;
for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd_func); i++) { - if (cmd == hns3_dbg_cmd_func[i].cmd) - return hns3_dbg_cmd_func[i].dbg_dump(handle, buf, len); + if (cmd == hns3_dbg_cmd_func[i].cmd) { + cmd_func = &hns3_dbg_cmd_func[i]; + if (cmd_func->dbg_dump) + return cmd_func->dbg_dump(dbg_data->handle, buf, + len); + else + return cmd_func->dbg_dump_bd(dbg_data, buf, + len); + } }
if (!ops->dbg_read_cmd) return -EOPNOTSUPP;
- return ops->dbg_read_cmd(handle, cmd, buf, len); + return ops->dbg_read_cmd(dbg_data->handle, cmd, buf, len); }
static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { - struct hnae3_handle *handle = filp->private_data; + struct hns3_dbg_data *dbg_data = filp->private_data; + struct hnae3_handle *handle = dbg_data->handle; struct hns3_nic_priv *priv = handle->priv; ssize_t size = 0; char **save_buf; @@ -654,7 +761,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
/* get data ready for the first time to read */ if (!*ppos) { - ret = hns3_dbg_read_cmd(handle, hns3_dbg_cmd[index].cmd, + ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd, read_buf, hns3_dbg_cmd[index].buf_len); if (ret) goto out; @@ -688,14 +795,47 @@ static const struct file_operations hns3_dbg_fops = { .read = hns3_dbg_read, };
+static int hns3_dbg_bd_file_init(struct hnae3_handle *handle, u32 cmd) +{ + struct dentry *entry_dir; + struct hns3_dbg_data *data; + u16 max_queue_num; + unsigned int i; + + entry_dir = hns3_dbg_dentry[hns3_dbg_cmd[cmd].dentry].dentry; + max_queue_num = hns3_get_max_available_channels(handle); + data = devm_kzalloc(&handle->pdev->dev, max_queue_num * sizeof(*data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + for (i = 0; i < max_queue_num; i++) { + char name[HNS3_DBG_FILE_NAME_LEN]; + + data[i].handle = handle; + data[i].qid = i; + sprintf(name, "%s%u", hns3_dbg_cmd[cmd].name, i); + debugfs_create_file(name, 0400, entry_dir, &data[i], + &hns3_dbg_fops); + } + + return 0; +} + static int hns3_dbg_common_file_init(struct hnae3_handle *handle, u32 cmd) { + struct hns3_dbg_data *data; struct dentry *entry_dir;
+ data = devm_kzalloc(&handle->pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->handle = handle; entry_dir = hns3_dbg_dentry[hns3_dbg_cmd[cmd].dentry].dentry; debugfs_create_file(hns3_dbg_cmd[cmd].name, 0400, entry_dir, - handle, &hns3_dbg_fops); + data, &hns3_dbg_fops);
return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index d16ec876bc71..06868b618010 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -5,10 +5,28 @@ #define __HNS3_DEBUGFS_H
#define HNS3_DBG_READ_LEN 65536 +#define HNS3_DBG_READ_LEN_4MB 0x400000 #define HNS3_DBG_WRITE_LEN 1024
+#define HNS3_DBG_DATA_STR_LEN 32 +#define HNS3_DBG_INFO_LEN 256 +#define HNS3_DBG_ITEM_NAME_LEN 32 +#define HNS3_DBG_FILE_NAME_LEN 16 + +struct hns3_dbg_item { + char name[HNS3_DBG_ITEM_NAME_LEN]; + u16 interval; /* blank numbers after the item */ +}; + +struct hns3_dbg_data { + struct hnae3_handle *handle; + u16 qid; +}; + enum hns3_dbg_dentry_type { HNS3_DBG_DENTRY_TM, + HNS3_DBG_DENTRY_TX_BD, + HNS3_DBG_DENTRY_RX_BD, HNS3_DBG_DENTRY_COMMON, };
@@ -29,6 +47,7 @@ struct hns3_dbg_cmd_info { struct hns3_dbg_func { enum hnae3_dbg_cmd cmd; int (*dbg_dump)(struct hnae3_handle *handle, char *buf, int len); + int (*dbg_dump_bd)(struct hns3_dbg_data *data, char *buf, int len); };
struct hns3_dbg_cap_info { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 77ec11f7ce25..2fb9143f98d2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -634,7 +634,7 @@ static int hns3_nic_set_real_num_queue(struct net_device *netdev) return 0; }
-static u16 hns3_get_max_available_channels(struct hnae3_handle *h) +u16 hns3_get_max_available_channels(struct hnae3_handle *h) { u16 alloc_tqps, max_rss_size, rss_size;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 5c72f41cf57e..79ff2fa61d47 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -655,4 +655,5 @@ void hns3_dbg_uninit(struct hnae3_handle *handle); void hns3_dbg_register_debugfs(const char *debugfs_dir_name); void hns3_dbg_unregister_debugfs(void); void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size); +u16 hns3_get_max_available_channels(struct hnae3_handle *h); #endif
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 1556ea9120ffcf4faf7ac6b62a6e28216f260a23 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for mac list info is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create two files "uc" and "mc" under directory "mac_list" for it, and query mac list info by "cat mac_list/uc" and "mac_list/mc", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat mac_list/uc UC MAC_LIST: FUNC_ID MAC_ADDR STATE pf 00:18:2d:00:00:71 ACTIVE
$ cat mac_list/mc MC MAC_LIST: FUNC_ID MAC_ADDR STATE pf 01:80:c2:00:00:21 ACTIVE
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 19 ++- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 1 + .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 127 +++++++++++++----- .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 9 ++ 5 files changed, 119 insertions(+), 39 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 5b030e92b56c..98c79b847e63 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -256,6 +256,8 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, + HNAE3_DBG_CMD_MAC_UC, + HNAE3_DBG_CMD_MAC_MC, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index fb3c2d4fbcc5..5e0278604c12 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -20,6 +20,9 @@ static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { { .name = "rx_bd_info" }, + { + .name = "mac_list" + }, /* keep common at the bottom and add new directory above */ { .name = "common" @@ -73,6 +76,20 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN_4MB, .init = hns3_dbg_bd_file_init, }, + { + .name = "uc", + .cmd = HNAE3_DBG_CMD_MAC_UC, + .dentry = HNS3_DBG_DENTRY_MAC, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "mc", + .cmd = HNAE3_DBG_CMD_MAC_MC, + .dentry = HNS3_DBG_DENTRY_MAC, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -474,8 +491,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump loopback\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); - dev_info(&h->pdev->dev, "dump uc mac list <func id>\n"); - dev_info(&h->pdev->dev, "dump mc mac list <func id>\n"); dev_info(&h->pdev->dev, "dump intr\n");
memset(printf_buf, 0, HNS3_DBG_BUF_LEN); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index 06868b618010..3d2ee3642459 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -27,6 +27,7 @@ enum hns3_dbg_dentry_type { HNS3_DBG_DENTRY_TM, HNS3_DBG_DENTRY_TX_BD, HNS3_DBG_DENTRY_RX_BD, + HNS3_DBG_DENTRY_MAC, HNS3_DBG_DENTRY_COMMON, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 7f1abdff25b0..ea0d43fa9149 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -8,6 +8,10 @@ #include "hclge_tm.h" #include "hnae3.h"
+static const char * const hclge_mac_state_str[] = { + "TO_ADD", "TO_DEL", "ACTIVE" +}; + static const struct hclge_dbg_reg_type_info hclge_dbg_reg_info[] = { { .reg_type = "bios common", .dfx_msg = &hclge_dbg_bios_common_reg[0], @@ -71,6 +75,35 @@ static const struct hclge_dbg_reg_type_info hclge_dbg_reg_info[] = { .cmd = HCLGE_OPC_DFX_TQP_REG } }, };
+static void hclge_dbg_fill_content(char *content, u16 len, + const struct hclge_dbg_item *items, + const char **result, u16 size) +{ + char *pos = content; + u16 i; + + memset(content, ' ', len); + for (i = 0; i < size; i++) { + if (result) + strncpy(pos, result[i], strlen(result[i])); + else + strncpy(pos, items[i].name, strlen(items[i].name)); + pos += strlen(items[i].name) + items[i].interval; + } + *pos++ = '\n'; + *pos++ = '\0'; +} + +static char *hclge_dbg_get_func_id_str(char *buf, u8 id) +{ + if (id) + sprintf(buf, "vf%u", id - 1); + else + sprintf(buf, "pf"); + + return buf; +} + static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset) { struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; @@ -1693,45 +1726,65 @@ static void hclge_dbg_dump_qs_shaper(struct hclge_dev *hdev, hclge_dbg_dump_qs_shaper_single(hdev, qsid); }
-static int hclge_dbg_dump_mac_list(struct hclge_dev *hdev, const char *cmd_buf, - bool is_unicast) +static const struct hclge_dbg_item mac_list_items[] = { + { "FUNC_ID", 2 }, + { "MAC_ADDR", 12 }, + { "STATE", 2 }, +}; + +static void hclge_dbg_dump_mac_list(struct hclge_dev *hdev, char *buf, int len, + bool is_unicast) { + char data_str[ARRAY_SIZE(mac_list_items)][HCLGE_DBG_DATA_STR_LEN]; + char content[HCLGE_DBG_INFO_LEN], str_id[HCLGE_DBG_ID_LEN]; + char *result[ARRAY_SIZE(mac_list_items)]; struct hclge_mac_node *mac_node, *tmp; struct hclge_vport *vport; struct list_head *list; u32 func_id; - int ret; - - ret = kstrtouint(cmd_buf, 0, &func_id); - if (ret < 0) { - dev_err(&hdev->pdev->dev, - "dump mac list: bad command string, ret = %d\n", ret); - return -EINVAL; - } + int pos = 0; + int i;
- if (func_id >= hdev->num_alloc_vport) { - dev_err(&hdev->pdev->dev, - "function id(%u) is out of range(0-%u)\n", func_id, - hdev->num_alloc_vport - 1); - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(mac_list_items); i++) + result[i] = &data_str[i][0]; + + pos += scnprintf(buf + pos, len - pos, "%s MAC_LIST:\n", + is_unicast ? "UC" : "MC"); + hclge_dbg_fill_content(content, sizeof(content), mac_list_items, + NULL, ARRAY_SIZE(mac_list_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + + for (func_id = 0; func_id < hdev->num_alloc_vport; func_id++) { + vport = &hdev->vport[func_id]; + list = is_unicast ? &vport->uc_mac_list : &vport->mc_mac_list; + spin_lock_bh(&vport->mac_list_lock); + list_for_each_entry_safe(mac_node, tmp, list, node) { + i = 0; + result[i++] = hclge_dbg_get_func_id_str(str_id, + func_id); + sprintf(result[i++], "%pM", mac_node->mac_addr); + sprintf(result[i++], "%5s", + hclge_mac_state_str[mac_node->state]); + hclge_dbg_fill_content(content, sizeof(content), + mac_list_items, + (const char **)result, + ARRAY_SIZE(mac_list_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + } + spin_unlock_bh(&vport->mac_list_lock); } +}
- vport = &hdev->vport[func_id]; - - list = is_unicast ? &vport->uc_mac_list : &vport->mc_mac_list; - - dev_info(&hdev->pdev->dev, "vport %u %s mac list:\n", - func_id, is_unicast ? "uc" : "mc"); - dev_info(&hdev->pdev->dev, "mac address state\n"); - - spin_lock_bh(&vport->mac_list_lock); +static int hclge_dbg_dump_mac_uc(struct hclge_dev *hdev, char *buf, int len) +{ + hclge_dbg_dump_mac_list(hdev, buf, len, true);
- list_for_each_entry_safe(mac_node, tmp, list, node) { - dev_info(&hdev->pdev->dev, "%pM %d\n", - mac_node->mac_addr, mac_node->state); - } + return 0; +}
- spin_unlock_bh(&vport->mac_list_lock); +static int hclge_dbg_dump_mac_mc(struct hclge_dev *hdev, char *buf, int len) +{ + hclge_dbg_dump_mac_list(hdev, buf, len, false);
return 0; } @@ -1781,14 +1834,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { hclge_dbg_dump_qs_shaper(hdev, &cmd_buf[sizeof("dump qs shaper")]); - } else if (strncmp(cmd_buf, "dump uc mac list", 16) == 0) { - hclge_dbg_dump_mac_list(hdev, - &cmd_buf[sizeof("dump uc mac list")], - true); - } else if (strncmp(cmd_buf, "dump mc mac list", 16) == 0) { - hclge_dbg_dump_mac_list(hdev, - &cmd_buf[sizeof("dump mc mac list")], - false); } else if (strncmp(cmd_buf, DUMP_INTERRUPT, strlen(DUMP_INTERRUPT)) == 0) { hclge_dbg_dump_interrupt(hdev); @@ -1813,6 +1858,14 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_TM_QSET, .dbg_dump = hclge_dbg_dump_tm_qset, }, + { + .cmd = HNAE3_DBG_CMD_MAC_UC, + .dbg_dump = hclge_dbg_dump_mac_uc, + }, + { + .cmd = HNAE3_DBG_CMD_MAC_MC, + .dbg_dump = hclge_dbg_dump_mac_mc, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index 0c144532e6ad..c5c18afb8b88 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -728,4 +728,13 @@ static const struct hclge_dbg_dfx_message hclge_dbg_tqp_reg[] = { {true, "RCB_CFG_TX_RING_EBDNUM"}, };
+#define HCLGE_DBG_INFO_LEN 256 +#define HCLGE_DBG_ID_LEN 16 +#define HCLGE_DBG_ITEM_NAME_LEN 32 +#define HCLGE_DBG_DATA_STR_LEN 32 +struct hclge_dbg_item { + char name[HCLGE_DBG_ITEM_NAME_LEN]; + u16 interval; /* blank numbers after the item */ +}; + #endif
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit 8ddfd9c46ef49ed75abc745c1f90532a2abb8f01 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for mng tbl is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "mng_tbl" for it, and query it by command "cat mng_tbl", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat mng_tbl entry mac_addr mask ether mask vlan mask i_map ... 00 00:00:00:00:00:00 0 88cc 0 0000 1 0f ...
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 80 +++++++++---------- .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 1 - 4 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 98c79b847e63..c8515327ba98 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -258,6 +258,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_RX_BD, HNAE3_DBG_CMD_MAC_UC, HNAE3_DBG_CMD_MAC_MC, + HNAE3_DBG_CMD_MNG_TBL, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 5e0278604c12..4af997d6bd59 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -90,6 +90,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "mng_tbl", + .cmd = HNAE3_DBG_CMD_MNG_TBL, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -484,7 +491,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); - dev_info(&h->pdev->dev, "dump mng tbl\n"); dev_info(&h->pdev->dev, "dump reset info\n"); dev_info(&h->pdev->dev, "dump m7 info\n"); dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index ea0d43fa9149..613730f36148 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1212,24 +1212,19 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) "dump qos buf cfg fail(0x%x), ret = %d\n", cmd, ret); }
-static void hclge_dbg_dump_mng_table(struct hclge_dev *hdev) +static int hclge_dbg_dump_mng_table(struct hclge_dev *hdev, char *buf, int len) { struct hclge_mac_ethertype_idx_rd_cmd *req0; - char printf_buf[HCLGE_DBG_BUF_LEN]; struct hclge_desc desc; u32 msg_egress_port; + int pos = 0; int ret, i;
- dev_info(&hdev->pdev->dev, "mng tab:\n"); - memset(printf_buf, 0, HCLGE_DBG_BUF_LEN); - strncat(printf_buf, - "entry|mac_addr |mask|ether|mask|vlan|mask", - HCLGE_DBG_BUF_LEN - 1); - strncat(printf_buf + strlen(printf_buf), - "|i_map|i_dir|e_type|pf_id|vf_id|q_id|drop\n", - HCLGE_DBG_BUF_LEN - strlen(printf_buf) - 1); - - dev_info(&hdev->pdev->dev, "%s", printf_buf); + pos += scnprintf(buf + pos, len - pos, + "entry mac_addr mask ether "); + pos += scnprintf(buf + pos, len - pos, + "mask vlan mask i_map i_dir e_type "); + pos += scnprintf(buf + pos, len - pos, "pf_id vf_id q_id drop\n");
for (i = 0; i < HCLGE_DBG_MNG_TBL_MAX; i++) { hclge_cmd_setup_basic_desc(&desc, HCLGE_MAC_ETHERTYPE_IDX_RD, @@ -1240,43 +1235,40 @@ static void hclge_dbg_dump_mng_table(struct hclge_dev *hdev) ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "call hclge_cmd_send fail, ret = %d\n", ret); - return; + "failed to dump manage table, ret = %d\n", ret); + return ret; }
if (!req0->resp_code) continue;
- memset(printf_buf, 0, HCLGE_DBG_BUF_LEN); - snprintf(printf_buf, HCLGE_DBG_BUF_LEN, - "%02u |%02x:%02x:%02x:%02x:%02x:%02x|", - le16_to_cpu(req0->index), - req0->mac_addr[0], req0->mac_addr[1], - req0->mac_addr[2], req0->mac_addr[3], - req0->mac_addr[4], req0->mac_addr[5]); - - snprintf(printf_buf + strlen(printf_buf), - HCLGE_DBG_BUF_LEN - strlen(printf_buf), - "%x |%04x |%x |%04x|%x |%02x |%02x |", - !!(req0->flags & HCLGE_DBG_MNG_MAC_MASK_B), - le16_to_cpu(req0->ethter_type), - !!(req0->flags & HCLGE_DBG_MNG_ETHER_MASK_B), - le16_to_cpu(req0->vlan_tag) & HCLGE_DBG_MNG_VLAN_TAG, - !!(req0->flags & HCLGE_DBG_MNG_VLAN_MASK_B), - req0->i_port_bitmap, req0->i_port_direction); + pos += scnprintf(buf + pos, len - pos, "%02u %pM ", + le16_to_cpu(req0->index), req0->mac_addr); + + pos += scnprintf(buf + pos, len - pos, + "%x %04x %x %04x ", + !!(req0->flags & HCLGE_DBG_MNG_MAC_MASK_B), + le16_to_cpu(req0->ethter_type), + !!(req0->flags & HCLGE_DBG_MNG_ETHER_MASK_B), + le16_to_cpu(req0->vlan_tag) & + HCLGE_DBG_MNG_VLAN_TAG); + + pos += scnprintf(buf + pos, len - pos, + "%x %02x %02x ", + !!(req0->flags & HCLGE_DBG_MNG_VLAN_MASK_B), + req0->i_port_bitmap, req0->i_port_direction);
msg_egress_port = le16_to_cpu(req0->egress_port); - snprintf(printf_buf + strlen(printf_buf), - HCLGE_DBG_BUF_LEN - strlen(printf_buf), - "%x |%x |%02x |%04x|%x\n", - !!(msg_egress_port & HCLGE_DBG_MNG_E_TYPE_B), - msg_egress_port & HCLGE_DBG_MNG_PF_ID, - (msg_egress_port >> 3) & HCLGE_DBG_MNG_VF_ID, - le16_to_cpu(req0->egress_queue), - !!(msg_egress_port & HCLGE_DBG_MNG_DROP_B)); - - dev_info(&hdev->pdev->dev, "%s", printf_buf); + pos += scnprintf(buf + pos, len - pos, + "%x %x %02x %04x %x\n", + !!(msg_egress_port & HCLGE_DBG_MNG_E_TYPE_B), + msg_egress_port & HCLGE_DBG_MNG_PF_ID, + (msg_egress_port >> 3) & HCLGE_DBG_MNG_VF_ID, + le16_to_cpu(req0->egress_queue), + !!(msg_egress_port & HCLGE_DBG_MNG_DROP_B)); } + + return 0; }
static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage, @@ -1813,8 +1805,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_qos_pri_map(hdev); } else if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { hclge_dbg_dump_qos_buf_cfg(hdev); - } else if (strncmp(cmd_buf, "dump mng tbl", 12) == 0) { - hclge_dbg_dump_mng_table(hdev); } else if (strncmp(cmd_buf, DUMP_REG, strlen(DUMP_REG)) == 0) { hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]); } else if (strncmp(cmd_buf, "dump reset info", 15) == 0) { @@ -1866,6 +1856,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_MAC_MC, .dbg_dump = hclge_dbg_dump_mac_mc, }, + { + .cmd = HNAE3_DBG_CMD_MNG_TBL, + .dbg_dump = hclge_dbg_dump_mng_table, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index c5c18afb8b88..bf6a0ff66047 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -7,7 +7,6 @@ #include <linux/etherdevice.h> #include "hclge_cmd.h"
-#define HCLGE_DBG_BUF_LEN 256 #define HCLGE_DBG_MNG_TBL_MAX 64
#define HCLGE_DBG_MNG_VLAN_MASK_B BIT(0)
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit d658ff34dd7ff9ccf13c59a7c464b55ca122977d category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for loopback is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "loopback" for it, and query it by command "cat loopback", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat loopback mac id: 0 app loopback: off serdes serial loopback: off serdes parallel loopback: off
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 44 +++++++++++-------- 3 files changed, 33 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c8515327ba98..58ca5a5bd9f8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -259,6 +259,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_MAC_UC, HNAE3_DBG_CMD_MAC_MC, HNAE3_DBG_CMD_MNG_TBL, + HNAE3_DBG_CMD_LOOPBACK, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 4af997d6bd59..d2e3965c66d4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -97,6 +97,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "loopback", + .cmd = HNAE3_DBG_CMD_LOOPBACK, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -495,7 +502,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump m7 info\n"); dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); - dev_info(&h->pdev->dev, "dump loopback\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); dev_info(&h->pdev->dev, "dump intr\n");
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 613730f36148..7c02973ae218 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -8,6 +8,7 @@ #include "hclge_tm.h" #include "hnae3.h"
+static const char * const state_str[] = { "off", "on" }; static const char * const hclge_mac_state_str[] = { "TO_ADD", "TO_DEL", "ACTIVE" }; @@ -1566,32 +1567,34 @@ static void hclge_dbg_dump_ncl_config(struct hclge_dev *hdev, } }
-static void hclge_dbg_dump_loopback(struct hclge_dev *hdev) +static int hclge_dbg_dump_loopback(struct hclge_dev *hdev, char *buf, int len) { struct phy_device *phydev = hdev->hw.mac.phydev; struct hclge_config_mac_mode_cmd *req_app; struct hclge_common_lb_cmd *req_common; struct hclge_desc desc; u8 loopback_en; + int pos = 0; int ret;
req_app = (struct hclge_config_mac_mode_cmd *)desc.data; req_common = (struct hclge_common_lb_cmd *)desc.data;
- dev_info(&hdev->pdev->dev, "mac id: %u\n", hdev->hw.mac.mac_id); + pos += scnprintf(buf + pos, len - pos, "mac id: %u\n", + hdev->hw.mac.mac_id);
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAC_MODE, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, "failed to dump app loopback status, ret = %d\n", ret); - return; + return ret; }
loopback_en = hnae3_get_bit(le32_to_cpu(req_app->txrx_pad_fcs_loop_en), HCLGE_MAC_APP_LP_B); - dev_info(&hdev->pdev->dev, "app loopback: %s\n", - loopback_en ? "on" : "off"); + pos += scnprintf(buf + pos, len - pos, "app loopback: %s\n", + state_str[loopback_en]);
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -1599,27 +1602,30 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev) dev_err(&hdev->pdev->dev, "failed to dump common loopback status, ret = %d\n", ret); - return; + return ret; }
loopback_en = req_common->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; - dev_info(&hdev->pdev->dev, "serdes serial loopback: %s\n", - loopback_en ? "on" : "off"); + pos += scnprintf(buf + pos, len - pos, "serdes serial loopback: %s\n", + state_str[loopback_en]);
loopback_en = req_common->enable & - HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B; - dev_info(&hdev->pdev->dev, "serdes parallel loopback: %s\n", - loopback_en ? "on" : "off"); + HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B ? 1 : 0; + pos += scnprintf(buf + pos, len - pos, "serdes parallel loopback: %s\n", + state_str[loopback_en]);
if (phydev) { - dev_info(&hdev->pdev->dev, "phy loopback: %s\n", - phydev->loopback_enabled ? "on" : "off"); + loopback_en = phydev->loopback_enabled; + pos += scnprintf(buf + pos, len - pos, "phy loopback: %s\n", + state_str[loopback_en]); } else if (hnae3_dev_phy_imp_supported(hdev)) { loopback_en = req_common->enable & HCLGE_CMD_GE_PHY_INNER_LOOP_B; - dev_info(&hdev->pdev->dev, "phy loopback: %s\n", - loopback_en ? "on" : "off"); + pos += scnprintf(buf + pos, len - pos, "phy loopback: %s\n", + state_str[loopback_en]); } + + return 0; }
/* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt @@ -1785,7 +1791,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { #define DUMP_REG "dump reg" #define DUMP_TM_MAP "dump tm map" -#define DUMP_LOOPBACK "dump loopback" #define DUMP_INTERRUPT "dump intr"
struct hclge_vport *vport = hclge_get_vport(handle); @@ -1818,9 +1823,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) &cmd_buf[sizeof("dump ncl_config")]); } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { hclge_dbg_dump_mac_tnl_status(hdev); - } else if (strncmp(cmd_buf, DUMP_LOOPBACK, - strlen(DUMP_LOOPBACK)) == 0) { - hclge_dbg_dump_loopback(hdev); } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { hclge_dbg_dump_qs_shaper(hdev, &cmd_buf[sizeof("dump qs shaper")]); @@ -1860,6 +1862,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_MNG_TBL, .dbg_dump = hclge_dbg_dump_mng_table, }, + { + .cmd = HNAE3_DBG_CMD_LOOPBACK, + .dbg_dump = hclge_dbg_dump_loopback, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 9149ca0f115acf44f8473c0a1e464e716c4ca83b category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for intr is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "interrupt_info" for it, and query it by command "cat interrupt_info", return the result to userspace, rather than record in dmesg.
The display style is below: $cat interrupt_info num_nic_msi: 65 num_roce_msi: 65 num_msi_used: 2 num_msi_left: 128
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +++++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 26 ++++++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 58ca5a5bd9f8..4d8294b43eab 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -260,6 +260,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_MAC_MC, HNAE3_DBG_CMD_MNG_TBL, HNAE3_DBG_CMD_LOOPBACK, + HNAE3_DBG_CMD_INTERRUPT_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index d2e3965c66d4..0eb5eda10ee0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -104,6 +104,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "interrupt_info", + .cmd = HNAE3_DBG_CMD_INTERRUPT_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -503,7 +510,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); - dev_info(&h->pdev->dev, "dump intr\n");
memset(printf_buf, 0, HNS3_DBG_BUF_LEN); strncat(printf_buf, "dump reg [[bios common] [ssu <port_id>]", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 7c02973ae218..c3d84a4bd734 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1430,12 +1430,20 @@ static void hclge_dbg_dump_serv_info(struct hclge_dev *hdev) hdev->serv_processed_cnt); }
-static void hclge_dbg_dump_interrupt(struct hclge_dev *hdev) +static int hclge_dbg_dump_interrupt(struct hclge_dev *hdev, char *buf, int len) { - dev_info(&hdev->pdev->dev, "num_nic_msi: %u\n", hdev->num_nic_msi); - dev_info(&hdev->pdev->dev, "num_roce_msi: %u\n", hdev->num_roce_msi); - dev_info(&hdev->pdev->dev, "num_msi_used: %u\n", hdev->num_msi_used); - dev_info(&hdev->pdev->dev, "num_msi_left: %u\n", hdev->num_msi_left); + int pos = 0; + + pos += scnprintf(buf + pos, len - pos, "num_nic_msi: %u\n", + hdev->num_nic_msi); + pos += scnprintf(buf + pos, len - pos, "num_roce_msi: %u\n", + hdev->num_roce_msi); + pos += scnprintf(buf + pos, len - pos, "num_msi_used: %u\n", + hdev->num_msi_used); + pos += scnprintf(buf + pos, len - pos, "num_msi_left: %u\n", + hdev->num_msi_left); + + return 0; }
static void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev) @@ -1791,7 +1799,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { #define DUMP_REG "dump reg" #define DUMP_TM_MAP "dump tm map" -#define DUMP_INTERRUPT "dump intr"
struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; @@ -1826,9 +1833,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { hclge_dbg_dump_qs_shaper(hdev, &cmd_buf[sizeof("dump qs shaper")]); - } else if (strncmp(cmd_buf, DUMP_INTERRUPT, - strlen(DUMP_INTERRUPT)) == 0) { - hclge_dbg_dump_interrupt(hdev); } else { dev_info(&hdev->pdev->dev, "unknown command\n"); return -EINVAL; @@ -1866,6 +1870,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_LOOPBACK, .dbg_dump = hclge_dbg_dump_loopback, }, + { + .cmd = HNAE3_DBG_CMD_INTERRUPT_INFO, + .dbg_dump = hclge_dbg_dump_interrupt, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 1a7ff8280b16fe8a085e24aca9008724700d6878 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for reset info is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "reset_info" for it, and query it by command "cat reset_info", return the result to userspace, rather than record in dmesg.
The display style is below: $cat reset_info PF reset count: 0 FLR reset count: 0 GLOBAL reset count: 0 IMP reset count: 0 reset done count: 0 HW reset done count: 0 reset count: 0 reset fail count: 0 vector0 interrupt enable status: 0x1 reset interrupt source: 0x0 reset interrupt status: 0x0 RAS interrupt status:0x0 hardware reset status: 0x0 handshake status: 0x80 function reset status: 0x0
Change to the "hclge_show_rst_info" in the "hclge_reset_err_handle", when the reset fails, display reset info immediately.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 76 +++++++++++-------- .../hisilicon/hns3/hns3pf/hclge_main.c | 17 ++++- .../hisilicon/hns3/hns3pf/hclge_main.h | 4 +- 5 files changed, 71 insertions(+), 35 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 4d8294b43eab..57dc5e69a5fc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -261,6 +261,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_MNG_TBL, HNAE3_DBG_CMD_LOOPBACK, HNAE3_DBG_CMD_INTERRUPT_INFO, + HNAE3_DBG_CMD_RESET_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 0eb5eda10ee0..49c87c8ac37f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -111,6 +111,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "reset_info", + .cmd = HNAE3_DBG_CMD_RESET_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -505,7 +512,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); - dev_info(&h->pdev->dev, "dump reset info\n"); dev_info(&h->pdev->dev, "dump m7 info\n"); dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index c3d84a4bd734..736746b6ff75 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -4,6 +4,7 @@ #include <linux/device.h>
#include "hclge_debugfs.h" +#include "hclge_err.h" #include "hclge_main.h" #include "hclge_tm.h" #include "hnae3.h" @@ -1389,37 +1390,46 @@ static void hclge_dbg_fd_tcam(struct hclge_dev *hdev) kfree(rule_locs); }
-void hclge_dbg_dump_rst_info(struct hclge_dev *hdev) +int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len) { - dev_info(&hdev->pdev->dev, "PF reset count: %u\n", - hdev->rst_stats.pf_rst_cnt); - dev_info(&hdev->pdev->dev, "FLR reset count: %u\n", - hdev->rst_stats.flr_rst_cnt); - dev_info(&hdev->pdev->dev, "GLOBAL reset count: %u\n", - hdev->rst_stats.global_rst_cnt); - dev_info(&hdev->pdev->dev, "IMP reset count: %u\n", - hdev->rst_stats.imp_rst_cnt); - dev_info(&hdev->pdev->dev, "reset done count: %u\n", - hdev->rst_stats.reset_done_cnt); - dev_info(&hdev->pdev->dev, "HW reset done count: %u\n", - hdev->rst_stats.hw_reset_done_cnt); - dev_info(&hdev->pdev->dev, "reset count: %u\n", - hdev->rst_stats.reset_cnt); - dev_info(&hdev->pdev->dev, "reset fail count: %u\n", - hdev->rst_stats.reset_fail_cnt); - dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n", - hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_REG_BASE)); - dev_info(&hdev->pdev->dev, "reset interrupt source: 0x%x\n", - hclge_read_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG)); - dev_info(&hdev->pdev->dev, "reset interrupt status: 0x%x\n", - hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS)); - dev_info(&hdev->pdev->dev, "hardware reset status: 0x%x\n", - hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG)); - dev_info(&hdev->pdev->dev, "handshake status: 0x%x\n", - hclge_read_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG)); - dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n", - hclge_read_dev(&hdev->hw, HCLGE_FUN_RST_ING)); - dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state); + int pos = 0; + + pos += scnprintf(buf + pos, len - pos, "PF reset count: %u\n", + hdev->rst_stats.pf_rst_cnt); + pos += scnprintf(buf + pos, len - pos, "FLR reset count: %u\n", + hdev->rst_stats.flr_rst_cnt); + pos += scnprintf(buf + pos, len - pos, "GLOBAL reset count: %u\n", + hdev->rst_stats.global_rst_cnt); + pos += scnprintf(buf + pos, len - pos, "IMP reset count: %u\n", + hdev->rst_stats.imp_rst_cnt); + pos += scnprintf(buf + pos, len - pos, "reset done count: %u\n", + hdev->rst_stats.reset_done_cnt); + pos += scnprintf(buf + pos, len - pos, "HW reset done count: %u\n", + hdev->rst_stats.hw_reset_done_cnt); + pos += scnprintf(buf + pos, len - pos, "reset count: %u\n", + hdev->rst_stats.reset_cnt); + pos += scnprintf(buf + pos, len - pos, "reset fail count: %u\n", + hdev->rst_stats.reset_fail_cnt); + pos += scnprintf(buf + pos, len - pos, + "vector0 interrupt enable status: 0x%x\n", + hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_REG_BASE)); + pos += scnprintf(buf + pos, len - pos, "reset interrupt source: 0x%x\n", + hclge_read_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG)); + pos += scnprintf(buf + pos, len - pos, "reset interrupt status: 0x%x\n", + hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS)); + pos += scnprintf(buf + pos, len - pos, "RAS interrupt status: 0x%x\n", + hclge_read_dev(&hdev->hw, + HCLGE_RAS_PF_OTHER_INT_STS_REG)); + pos += scnprintf(buf + pos, len - pos, "hardware reset status: 0x%x\n", + hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG)); + pos += scnprintf(buf + pos, len - pos, "handshake status: 0x%x\n", + hclge_read_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG)); + pos += scnprintf(buf + pos, len - pos, "function reset status: 0x%x\n", + hclge_read_dev(&hdev->hw, HCLGE_FUN_RST_ING)); + pos += scnprintf(buf + pos, len - pos, "hdev state: 0x%lx\n", + hdev->state); + + return 0; }
static void hclge_dbg_dump_serv_info(struct hclge_dev *hdev) @@ -1819,8 +1829,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_qos_buf_cfg(hdev); } else if (strncmp(cmd_buf, DUMP_REG, strlen(DUMP_REG)) == 0) { hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]); - } else if (strncmp(cmd_buf, "dump reset info", 15) == 0) { - hclge_dbg_dump_rst_info(hdev); } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); } else if (strncmp(cmd_buf, "dump m7 info", 12) == 0) { @@ -1874,6 +1882,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_INTERRUPT_INFO, .dbg_dump = hclge_dbg_dump_interrupt, }, + { + .cmd = HNAE3_DBG_CMD_RESET_INFO, + .dbg_dump = hclge_dbg_dump_rst_info, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 55b0453d3948..d4d3f0b247af 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3936,6 +3936,21 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) return ret; }
+static void hclge_show_rst_info(struct hclge_dev *hdev) +{ + char *buf; + + buf = kzalloc(HCLGE_DBG_RESET_INFO_LEN, GFP_KERNEL); + if (!buf) + return; + + hclge_dbg_dump_rst_info(hdev, buf, HCLGE_DBG_RESET_INFO_LEN); + + dev_info(&hdev->pdev->dev, "dump reset info:\n%s", buf); + + kfree(buf); +} + static bool hclge_reset_err_handle(struct hclge_dev *hdev) { #define MAX_RESET_FAIL_CNT 5 @@ -3966,7 +3981,7 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev)
dev_err(&hdev->pdev->dev, "Reset fail!\n");
- hclge_dbg_dump_rst_info(hdev); + hclge_show_rst_info(hdev);
set_bit(HCLGE_STATE_RST_FAIL, &hdev->state);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 9e17c02de403..8bf451ef0b05 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -148,6 +148,8 @@
#define HCLGE_MAX_QSET_NUM 1024
+#define HCLGE_DBG_RESET_INFO_LEN 1024 + enum HLCGE_PORT_TYPE { HOST_PORT, NETWORK_PORT @@ -1089,6 +1091,6 @@ int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, void hclge_report_hw_error(struct hclge_dev *hdev, enum hnae3_hw_error_type type); void hclge_inform_vf_promisc_info(struct hclge_vport *vport); -void hclge_dbg_dump_rst_info(struct hclge_dev *hdev); +int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); int hclge_push_vf_link_status(struct hclge_vport *vport); #endif
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 0b198b0d80ea091f2a917536a097adefb2eaa52f category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for m7 info is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "imp_info" for it, and query it by command "cat imp_info", return the result to userspace, rather than record in dmesg.
The display style is below: $cat imp_info offset | data 0x0000 | 0x00000000 0x00000000 0x0008 | 0x00000000 0x00000000 0x0010 | 0x00000000 0x00000001 0x0018 | 0x00000000 0x00000000 0x0020 | 0x00000000 0x00000000 0x0028 | 0x00000000 0x00000000 0x0030 | 0x00000000 0x00000000
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 2 +- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 10 +-- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 81 ++++++++++++------- 5 files changed, 64 insertions(+), 38 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 57dc5e69a5fc..de04b1929bb0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -262,6 +262,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_LOOPBACK, HNAE3_DBG_CMD_INTERRUPT_INFO, HNAE3_DBG_CMD_RESET_INFO, + HNAE3_DBG_CMD_IMP_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 49c87c8ac37f..d91c0051b78d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -118,6 +118,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "imp_info", + .cmd = HNAE3_DBG_CMD_IMP_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -512,7 +519,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); - dev_info(&h->pdev->dev, "dump m7 info\n"); dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 0df9ca311e6c..6aed30cc22f2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -471,7 +471,7 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev) struct hclge_desc desc; u32 compat = 0;
- hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_M7_COMPAT_CFG, false); + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_IMP_COMPAT_CFG, false);
req = (struct hclge_firmware_compat_cmd *)desc.data;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index c6cd273363d5..12558aa0fe0a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -267,10 +267,10 @@ enum hclge_opcode_type { /* NCL config command */ HCLGE_OPC_QUERY_NCL_CONFIG = 0x7011,
- /* M7 stats command */ - HCLGE_OPC_M7_STATS_BD = 0x7012, - HCLGE_OPC_M7_STATS_INFO = 0x7013, - HCLGE_OPC_M7_COMPAT_CFG = 0x701A, + /* IMP stats command */ + HCLGE_OPC_IMP_STATS_BD = 0x7012, + HCLGE_OPC_IMP_STATS_INFO = 0x7013, + HCLGE_OPC_IMP_COMPAT_CFG = 0x701A,
/* SFP command */ HCLGE_OPC_GET_SFP_EEPROM = 0x7100, @@ -1101,7 +1101,7 @@ struct hclge_fd_user_def_cfg_cmd { u8 rsv[12]; };
-struct hclge_get_m7_bd_cmd { +struct hclge_get_imp_bd_cmd { __le32 bd_num; u8 rsv[20]; }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 736746b6ff75..d0634ba3ba1c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1456,56 +1456,73 @@ static int hclge_dbg_dump_interrupt(struct hclge_dev *hdev, char *buf, int len) return 0; }
-static void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev) +static void hclge_dbg_imp_info_data_print(struct hclge_desc *desc_src, + char *buf, int len, u32 bd_num) { - struct hclge_desc *desc_src, *desc_tmp; - struct hclge_get_m7_bd_cmd *req; +#define HCLGE_DBG_IMP_INFO_PRINT_OFFSET 0x2 + + struct hclge_desc *desc_index = desc_src; + u32 offset = 0; + int pos = 0; + u32 i, j; + + pos += scnprintf(buf + pos, len - pos, "offset | data\n"); + + for (i = 0; i < bd_num; i++) { + j = 0; + while (j < HCLGE_DESC_DATA_LEN - 1) { + pos += scnprintf(buf + pos, len - pos, "0x%04x | ", + offset); + pos += scnprintf(buf + pos, len - pos, "0x%08x ", + le32_to_cpu(desc_index->data[j++])); + pos += scnprintf(buf + pos, len - pos, "0x%08x\n", + le32_to_cpu(desc_index->data[j++])); + offset += sizeof(u32) * HCLGE_DBG_IMP_INFO_PRINT_OFFSET; + } + desc_index++; + } +} + +static int +hclge_dbg_get_imp_stats_info(struct hclge_dev *hdev, char *buf, int len) +{ + struct hclge_get_imp_bd_cmd *req; + struct hclge_desc *desc_src; struct hclge_desc desc; - u32 bd_num, buf_len; - int ret, i; + u32 bd_num; + int ret;
- hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_M7_STATS_BD, true); + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_IMP_STATS_BD, true);
- req = (struct hclge_get_m7_bd_cmd *)desc.data; + req = (struct hclge_get_imp_bd_cmd *)desc.data; ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "get firmware statistics bd number failed, ret = %d\n", + "failed to get imp statistics bd number, ret = %d\n", ret); - return; + return ret; }
bd_num = le32_to_cpu(req->bd_num);
- buf_len = sizeof(struct hclge_desc) * bd_num; - desc_src = kzalloc(buf_len, GFP_KERNEL); + desc_src = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL); if (!desc_src) - return; + return -ENOMEM;
- desc_tmp = desc_src; - ret = hclge_dbg_cmd_send(hdev, desc_tmp, 0, bd_num, - HCLGE_OPC_M7_STATS_INFO); + ret = hclge_dbg_cmd_send(hdev, desc_src, 0, bd_num, + HCLGE_OPC_IMP_STATS_INFO); if (ret) { kfree(desc_src); dev_err(&hdev->pdev->dev, - "get firmware statistics failed, ret = %d\n", ret); - return; + "failed to get imp statistics, ret = %d\n", ret); + return ret; }
- for (i = 0; i < bd_num; i++) { - dev_info(&hdev->pdev->dev, "0x%08x 0x%08x 0x%08x\n", - le32_to_cpu(desc_tmp->data[0]), - le32_to_cpu(desc_tmp->data[1]), - le32_to_cpu(desc_tmp->data[2])); - dev_info(&hdev->pdev->dev, "0x%08x 0x%08x 0x%08x\n", - le32_to_cpu(desc_tmp->data[3]), - le32_to_cpu(desc_tmp->data[4]), - le32_to_cpu(desc_tmp->data[5])); - - desc_tmp++; - } + hclge_dbg_imp_info_data_print(desc_src, buf, len, bd_num);
kfree(desc_src); + + return 0; }
#define HCLGE_CMD_NCL_CONFIG_BD_NUM 5 @@ -1831,8 +1848,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]); } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); - } else if (strncmp(cmd_buf, "dump m7 info", 12) == 0) { - hclge_dbg_get_m7_stats_info(hdev); } else if (strncmp(cmd_buf, "dump ncl_config", 15) == 0) { hclge_dbg_dump_ncl_config(hdev, &cmd_buf[sizeof("dump ncl_config")]); @@ -1886,6 +1901,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_RESET_INFO, .dbg_dump = hclge_dbg_dump_rst_info, }, + { + .cmd = HNAE3_DBG_CMD_IMP_INFO, + .dbg_dump = hclge_dbg_get_imp_stats_info, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit e76e6886646b88b258f9deba92d49080f26028ae category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for ncl config is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "ncl_config" for it, and query it by command "cat ncl_config", return the result to userspace, rather than record in dmesg.
The display style is below: $cat ncl_config offset | data 0x0000 | 0x00000028 0x0004 | 0x00000400 0x0008 | 0x08040201 0x000c | 0x00000000 0x0010 | 0x00040004 0x0014 | 0x00040004 0x0018 | 0x00000000 0x001c | 0x00000000 0x0020 | 0x00040004
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 1 + .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 78 ++++++++----------- 4 files changed, 40 insertions(+), 48 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index de04b1929bb0..96b2761279c0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -263,6 +263,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_INTERRUPT_INFO, HNAE3_DBG_CMD_RESET_INFO, HNAE3_DBG_CMD_IMP_INFO, + HNAE3_DBG_CMD_NCL_CONFIG, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index d91c0051b78d..ba4ee8ca7e71 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -125,6 +125,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "ncl_config", + .cmd = HNAE3_DBG_CMD_NCL_CONFIG, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN_128KB, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -519,7 +526,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); - dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n");
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index 3d2ee3642459..a7af9277ae69 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -5,6 +5,7 @@ #define __HNS3_DEBUGFS_H
#define HNS3_DBG_READ_LEN 65536 +#define HNS3_DBG_READ_LEN_128KB 0x20000 #define HNS3_DBG_READ_LEN_4MB 0x400000 #define HNS3_DBG_WRITE_LEN 1024
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index d0634ba3ba1c..8a92ab448a19 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1526,80 +1526,63 @@ hclge_dbg_get_imp_stats_info(struct hclge_dev *hdev, char *buf, int len) }
#define HCLGE_CMD_NCL_CONFIG_BD_NUM 5 +#define HCLGE_MAX_NCL_CONFIG_LENGTH 16384
-static void hclge_ncl_config_data_print(struct hclge_dev *hdev, - struct hclge_desc *desc, int *offset, - int *length) +static void hclge_ncl_config_data_print(struct hclge_desc *desc, int *index, + char *buf, int *len, int *pos) { #define HCLGE_CMD_DATA_NUM 6
- int i; - int j; + int offset = HCLGE_MAX_NCL_CONFIG_LENGTH - *index; + int i, j;
for (i = 0; i < HCLGE_CMD_NCL_CONFIG_BD_NUM; i++) { for (j = 0; j < HCLGE_CMD_DATA_NUM; j++) { if (i == 0 && j == 0) continue;
- dev_info(&hdev->pdev->dev, "0x%04x | 0x%08x\n", - *offset, - le32_to_cpu(desc[i].data[j])); - *offset += sizeof(u32); - *length -= sizeof(u32); - if (*length <= 0) + *pos += scnprintf(buf + *pos, *len - *pos, + "0x%04x | 0x%08x\n", offset, + le32_to_cpu(desc[i].data[j])); + + offset += sizeof(u32); + *index -= sizeof(u32); + + if (*index <= 0) return; } } }
-/* hclge_dbg_dump_ncl_config: print specified range of NCL_CONFIG file - * @hdev: pointer to struct hclge_dev - * @cmd_buf: string that contains offset and length - */ -static void hclge_dbg_dump_ncl_config(struct hclge_dev *hdev, - const char *cmd_buf) +static int +hclge_dbg_dump_ncl_config(struct hclge_dev *hdev, char *buf, int len) { -#define HCLGE_MAX_NCL_CONFIG_OFFSET 4096 #define HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD (20 + 24 * 4) -#define HCLGE_NCL_CONFIG_PARAM_NUM 2
struct hclge_desc desc[HCLGE_CMD_NCL_CONFIG_BD_NUM]; int bd_num = HCLGE_CMD_NCL_CONFIG_BD_NUM; - int offset; - int length; - int data0; + int index = HCLGE_MAX_NCL_CONFIG_LENGTH; + int pos = 0; + u32 data0; int ret;
- ret = sscanf(cmd_buf, "%x %x", &offset, &length); - if (ret != HCLGE_NCL_CONFIG_PARAM_NUM) { - dev_err(&hdev->pdev->dev, - "Too few parameters, num = %d.\n", ret); - return; - } - - if (offset < 0 || offset >= HCLGE_MAX_NCL_CONFIG_OFFSET || - length <= 0 || length > HCLGE_MAX_NCL_CONFIG_OFFSET - offset) { - dev_err(&hdev->pdev->dev, - "Invalid input, offset = %d, length = %d.\n", - offset, length); - return; - } - - dev_info(&hdev->pdev->dev, "offset | data\n"); + pos += scnprintf(buf + pos, len - pos, "offset | data\n");
- while (length > 0) { - data0 = offset; - if (length >= HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD) + while (index > 0) { + data0 = HCLGE_MAX_NCL_CONFIG_LENGTH - index; + if (index >= HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD) data0 |= HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD << 16; else - data0 |= length << 16; + data0 |= (u32)index << 16; ret = hclge_dbg_cmd_send(hdev, desc, data0, bd_num, HCLGE_OPC_QUERY_NCL_CONFIG); if (ret) - return; + return ret;
- hclge_ncl_config_data_print(hdev, desc, &offset, &length); + hclge_ncl_config_data_print(desc, &index, buf, &len, &pos); } + + return 0; }
static int hclge_dbg_dump_loopback(struct hclge_dev *hdev, char *buf, int len) @@ -1848,9 +1831,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]); } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); - } else if (strncmp(cmd_buf, "dump ncl_config", 15) == 0) { - hclge_dbg_dump_ncl_config(hdev, - &cmd_buf[sizeof("dump ncl_config")]); } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { hclge_dbg_dump_mac_tnl_status(hdev); } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { @@ -1905,6 +1885,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_IMP_INFO, .dbg_dump = hclge_dbg_get_imp_stats_info, }, + { + .cmd = HNAE3_DBG_CMD_NCL_CONFIG, + .dbg_dump = hclge_dbg_dump_ncl_config, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-v5.13-rc4 commit 73a13d8dbe33e53a12400f2be0f5af169816c67f category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, when adaptive is on, the user's coalesce configuration may be overwritten by the dynamic one. The reason is that user's configurations are saved in struct hns3_enet_tqp_vector whose value maybe changed by the dynamic algorithm. To fix it, use struct hns3_nic_priv instead of struct hns3_enet_tqp_vector to save and get the user's configuration.
BTW, operations of storing and restoring coalesce info in the reset process are unnecessary now, so remove them as well.
Fixes: 434776a5fae2 ("net: hns3: add ethtool_ops.set_coalesce support to PF") Fixes: 7e96adc46633 ("net: hns3: add ethtool_ops.get_coalesce support to PF") Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 84 +++++++++---------- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 64 +++++--------- 2 files changed, 63 insertions(+), 85 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 2fb9143f98d2..87b037c88ca5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -536,22 +536,17 @@ static void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector, struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev); struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal; struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal; + struct hns3_enet_coalesce *ptx_coal = &priv->tx_coal; + struct hns3_enet_coalesce *prx_coal = &priv->rx_coal;
- /* initialize the configuration for interrupt coalescing. - * 1. GL (Interrupt Gap Limiter) - * 2. RL (Interrupt Rate Limiter) - * 3. QL (Interrupt Quantity Limiter) - * - * Default: enable interrupt coalescing self-adaptive and GL - */ - tx_coal->adapt_enable = 1; - rx_coal->adapt_enable = 1; + tx_coal->adapt_enable = ptx_coal->adapt_enable; + rx_coal->adapt_enable = prx_coal->adapt_enable;
- tx_coal->int_gl = HNS3_INT_GL_50K; - rx_coal->int_gl = HNS3_INT_GL_50K; + tx_coal->int_gl = ptx_coal->int_gl; + rx_coal->int_gl = prx_coal->int_gl;
- rx_coal->flow_level = HNS3_FLOW_LOW; - tx_coal->flow_level = HNS3_FLOW_LOW; + rx_coal->flow_level = prx_coal->flow_level; + tx_coal->flow_level = ptx_coal->flow_level;
/* device version above V3(include V3), GL can configure 1us * unit, so uses 1us unit. @@ -566,8 +561,8 @@ static void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector, rx_coal->ql_enable = 1; tx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max; rx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max; - tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG; - rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG; + tx_coal->int_ql = ptx_coal->int_ql; + rx_coal->int_ql = prx_coal->int_ql; } }
@@ -4145,6 +4140,34 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv) return ret; }
+static void hns3_nic_init_coal_cfg(struct hns3_nic_priv *priv) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev); + struct hns3_enet_coalesce *tx_coal = &priv->tx_coal; + struct hns3_enet_coalesce *rx_coal = &priv->rx_coal; + + /* initialize the configuration for interrupt coalescing. + * 1. GL (Interrupt Gap Limiter) + * 2. RL (Interrupt Rate Limiter) + * 3. QL (Interrupt Quantity Limiter) + * + * Default: enable interrupt coalescing self-adaptive and GL + */ + tx_coal->adapt_enable = 1; + rx_coal->adapt_enable = 1; + + tx_coal->int_gl = HNS3_INT_GL_50K; + rx_coal->int_gl = HNS3_INT_GL_50K; + + rx_coal->flow_level = HNS3_FLOW_LOW; + tx_coal->flow_level = HNS3_FLOW_LOW; + + if (ae_dev->dev_specs.int_ql_max) { + tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG; + rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG; + } +} + static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv) { struct hnae3_handle *h = priv->ae_handle; @@ -4596,6 +4619,8 @@ static int hns3_client_init(struct hnae3_handle *handle) goto out_get_ring_cfg; }
+ hns3_nic_init_coal_cfg(priv); + ret = hns3_nic_alloc_vector_data(priv); if (ret) { ret = -ENOMEM; @@ -4880,31 +4905,6 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h) return 0; }
-static void hns3_store_coal(struct hns3_nic_priv *priv) -{ - /* ethtool only support setting and querying one coal - * configuration for now, so save the vector 0' coal - * configuration here in order to restore it. - */ - memcpy(&priv->tx_coal, &priv->tqp_vector[0].tx_group.coal, - sizeof(struct hns3_enet_coalesce)); - memcpy(&priv->rx_coal, &priv->tqp_vector[0].rx_group.coal, - sizeof(struct hns3_enet_coalesce)); -} - -static void hns3_restore_coal(struct hns3_nic_priv *priv) -{ - u16 vector_num = priv->vector_num; - int i; - - for (i = 0; i < vector_num; i++) { - memcpy(&priv->tqp_vector[i].tx_group.coal, &priv->tx_coal, - sizeof(struct hns3_enet_coalesce)); - memcpy(&priv->tqp_vector[i].rx_group.coal, &priv->rx_coal, - sizeof(struct hns3_enet_coalesce)); - } -} - static int hns3_reset_notify_down_enet(struct hnae3_handle *handle) { struct hnae3_knic_private_info *kinfo = &handle->kinfo; @@ -4963,8 +4963,6 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle) if (ret) goto err_put_ring;
- hns3_restore_coal(priv); - ret = hns3_nic_init_vector_data(priv); if (ret) goto err_dealloc_vector; @@ -5030,8 +5028,6 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
hns3_nic_uninit_vector_data(priv);
- hns3_store_coal(priv); - hns3_nic_dealloc_vector_data(priv);
hns3_uninit_all_ring(priv); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index b48faf769b1c..c1ea403d2b56 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -1134,50 +1134,32 @@ static void hns3_get_channels(struct net_device *netdev, h->ae_algo->ops->get_channels(h, ch); }
-static int hns3_get_coalesce_per_queue(struct net_device *netdev, u32 queue, - struct ethtool_coalesce *cmd) +static int hns3_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *cmd) { - struct hns3_enet_tqp_vector *tx_vector, *rx_vector; struct hns3_nic_priv *priv = netdev_priv(netdev); + struct hns3_enet_coalesce *tx_coal = &priv->tx_coal; + struct hns3_enet_coalesce *rx_coal = &priv->rx_coal; struct hnae3_handle *h = priv->ae_handle; - u16 queue_num = h->kinfo.num_tqps;
if (hns3_nic_resetting(netdev)) return -EBUSY;
- if (queue >= queue_num) { - netdev_err(netdev, - "Invalid queue value %u! Queue max id=%u\n", - queue, queue_num - 1); - return -EINVAL; - } - - tx_vector = priv->ring[queue].tqp_vector; - rx_vector = priv->ring[queue_num + queue].tqp_vector; + cmd->use_adaptive_tx_coalesce = tx_coal->adapt_enable; + cmd->use_adaptive_rx_coalesce = rx_coal->adapt_enable;
- cmd->use_adaptive_tx_coalesce = - tx_vector->tx_group.coal.adapt_enable; - cmd->use_adaptive_rx_coalesce = - rx_vector->rx_group.coal.adapt_enable; - - cmd->tx_coalesce_usecs = tx_vector->tx_group.coal.int_gl; - cmd->rx_coalesce_usecs = rx_vector->rx_group.coal.int_gl; + cmd->tx_coalesce_usecs = tx_coal->int_gl; + cmd->rx_coalesce_usecs = rx_coal->int_gl;
cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting; cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting;
- cmd->tx_max_coalesced_frames = tx_vector->tx_group.coal.int_ql; - cmd->rx_max_coalesced_frames = rx_vector->rx_group.coal.int_ql; + cmd->tx_max_coalesced_frames = tx_coal->int_ql; + cmd->rx_max_coalesced_frames = rx_coal->int_ql;
return 0; }
-static int hns3_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *cmd) -{ - return hns3_get_coalesce_per_queue(netdev, 0, cmd); -} - static int hns3_check_gl_coalesce_para(struct net_device *netdev, struct ethtool_coalesce *cmd) { @@ -1292,19 +1274,7 @@ static int hns3_check_coalesce_para(struct net_device *netdev, return ret; }
- ret = hns3_check_ql_coalesce_param(netdev, cmd); - if (ret) - return ret; - - if (cmd->use_adaptive_tx_coalesce == 1 || - cmd->use_adaptive_rx_coalesce == 1) { - netdev_info(netdev, - "adaptive-tx=%u and adaptive-rx=%u, tx_usecs or rx_usecs will changed dynamically.\n", - cmd->use_adaptive_tx_coalesce, - cmd->use_adaptive_rx_coalesce); - } - - return 0; + return hns3_check_ql_coalesce_param(netdev, cmd); }
static void hns3_set_coalesce_per_queue(struct net_device *netdev, @@ -1350,6 +1320,9 @@ static int hns3_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *cmd) { struct hnae3_handle *h = hns3_get_handle(netdev); + struct hns3_nic_priv *priv = netdev_priv(netdev); + struct hns3_enet_coalesce *tx_coal = &priv->tx_coal; + struct hns3_enet_coalesce *rx_coal = &priv->rx_coal; u16 queue_num = h->kinfo.num_tqps; int ret; int i; @@ -1364,6 +1337,15 @@ static int hns3_set_coalesce(struct net_device *netdev, h->kinfo.int_rl_setting = hns3_rl_round_down(cmd->rx_coalesce_usecs_high);
+ tx_coal->adapt_enable = cmd->use_adaptive_tx_coalesce; + rx_coal->adapt_enable = cmd->use_adaptive_rx_coalesce; + + tx_coal->int_gl = cmd->tx_coalesce_usecs; + rx_coal->int_gl = cmd->rx_coalesce_usecs; + + tx_coal->int_ql = cmd->tx_max_coalesced_frames; + rx_coal->int_ql = cmd->rx_max_coalesced_frames; + for (i = 0; i < queue_num; i++) hns3_set_coalesce_per_queue(netdev, cmd, i);
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit d96b0e59468dcbd61417b7dd31985a700e58d3b2 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for reg is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create some files "bios_common/ssu/igu_egu/rpu/ncsi/rtc/ppp/rcb/tqp/mac" for it, and query it by command "cat xxx", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat bios_common BP_CPU_STATE: 0x0 DFX_MSIX_INFO_NIC_0: 0xc000 DFX_MSIX_INFO_NIC_1: 0x0 DFX_MSIX_INFO_NIC_2: 0x0 DFX_MSIX_INFO_NIC_3: 0x0 DFX_MSIX_INFO_ROC_0: 0xc000 DFX_MSIX_INFO_ROC_1: 0x0 DFX_MSIX_INFO_ROC_2: 0x0 DFX_MSIX_INFO_ROC_3: 0x0
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 10 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 84 ++++- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 1 + .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 356 ++++++++++++------ .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 4 +- 5 files changed, 321 insertions(+), 134 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 96b2761279c0..2a7de739b2ee 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -264,6 +264,16 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_RESET_INFO, HNAE3_DBG_CMD_IMP_INFO, HNAE3_DBG_CMD_NCL_CONFIG, + HNAE3_DBG_CMD_REG_BIOS_COMMON, + HNAE3_DBG_CMD_REG_SSU, + HNAE3_DBG_CMD_REG_IGU_EGU, + HNAE3_DBG_CMD_REG_RPU, + HNAE3_DBG_CMD_REG_NCSI, + HNAE3_DBG_CMD_REG_RTC, + HNAE3_DBG_CMD_REG_PPP, + HNAE3_DBG_CMD_REG_RCB, + HNAE3_DBG_CMD_REG_TQP, + HNAE3_DBG_CMD_REG_MAC, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index ba4ee8ca7e71..af0751e53f79 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -23,6 +23,9 @@ static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { { .name = "mac_list" }, + { + .name = "reg" + }, /* keep common at the bottom and add new directory above */ { .name = "common" @@ -132,6 +135,76 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN_128KB, .init = hns3_dbg_common_file_init, }, + { + .name = "bios_common", + .cmd = HNAE3_DBG_CMD_REG_BIOS_COMMON, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "ssu", + .cmd = HNAE3_DBG_CMD_REG_SSU, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "igu_egu", + .cmd = HNAE3_DBG_CMD_REG_IGU_EGU, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "rpu", + .cmd = HNAE3_DBG_CMD_REG_RPU, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "ncsi", + .cmd = HNAE3_DBG_CMD_REG_NCSI, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "rtc", + .cmd = HNAE3_DBG_CMD_REG_RTC, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "ppp", + .cmd = HNAE3_DBG_CMD_REG_PPP, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "rcb", + .cmd = HNAE3_DBG_CMD_REG_RCB, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "tqp", + .cmd = HNAE3_DBG_CMD_REG_TQP, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "mac", + .cmd = HNAE3_DBG_CMD_REG_MAC, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -529,17 +602,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n");
- memset(printf_buf, 0, HNS3_DBG_BUF_LEN); - strncat(printf_buf, "dump reg [[bios common] [ssu <port_id>]", - HNS3_DBG_BUF_LEN - 1); - strncat(printf_buf + strlen(printf_buf), - " [igu egu <port_id>] [rpu <tc_queue_num>]", - HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); - strncat(printf_buf + strlen(printf_buf), - " [rtc] [ppp] [rcb] [tqp <queue_num>] [mac]]\n", - HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); - dev_info(&h->pdev->dev, "%s", printf_buf); - memset(printf_buf, 0, HNS3_DBG_BUF_LEN); strncat(printf_buf, "dump reg dcb <port_id> <pri_id> <pg_id>", HNS3_DBG_BUF_LEN - 1); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index a7af9277ae69..6060bfc21850 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -29,6 +29,7 @@ enum hns3_dbg_dentry_type { HNS3_DBG_DENTRY_TX_BD, HNS3_DBG_DENTRY_RX_BD, HNS3_DBG_DENTRY_MAC, + HNS3_DBG_DENTRY_REG, HNS3_DBG_DENTRY_COMMON, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 8a92ab448a19..2f6662892edc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -15,62 +15,62 @@ static const char * const hclge_mac_state_str[] = { };
static const struct hclge_dbg_reg_type_info hclge_dbg_reg_info[] = { - { .reg_type = "bios common", + { .cmd = HNAE3_DBG_CMD_REG_BIOS_COMMON, .dfx_msg = &hclge_dbg_bios_common_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_bios_common_reg), .offset = HCLGE_DBG_DFX_BIOS_OFFSET, .cmd = HCLGE_OPC_DFX_BIOS_COMMON_REG } }, - { .reg_type = "ssu", + { .cmd = HNAE3_DBG_CMD_REG_SSU, .dfx_msg = &hclge_dbg_ssu_reg_0[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_0), .offset = HCLGE_DBG_DFX_SSU_0_OFFSET, .cmd = HCLGE_OPC_DFX_SSU_REG_0 } }, - { .reg_type = "ssu", + { .cmd = HNAE3_DBG_CMD_REG_SSU, .dfx_msg = &hclge_dbg_ssu_reg_1[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_1), .offset = HCLGE_DBG_DFX_SSU_1_OFFSET, .cmd = HCLGE_OPC_DFX_SSU_REG_1 } }, - { .reg_type = "ssu", + { .cmd = HNAE3_DBG_CMD_REG_SSU, .dfx_msg = &hclge_dbg_ssu_reg_2[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_2), .offset = HCLGE_DBG_DFX_SSU_2_OFFSET, .cmd = HCLGE_OPC_DFX_SSU_REG_2 } }, - { .reg_type = "igu egu", + { .cmd = HNAE3_DBG_CMD_REG_IGU_EGU, .dfx_msg = &hclge_dbg_igu_egu_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_igu_egu_reg), .offset = HCLGE_DBG_DFX_IGU_OFFSET, .cmd = HCLGE_OPC_DFX_IGU_EGU_REG } }, - { .reg_type = "rpu", + { .cmd = HNAE3_DBG_CMD_REG_RPU, .dfx_msg = &hclge_dbg_rpu_reg_0[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rpu_reg_0), .offset = HCLGE_DBG_DFX_RPU_0_OFFSET, .cmd = HCLGE_OPC_DFX_RPU_REG_0 } }, - { .reg_type = "rpu", + { .cmd = HNAE3_DBG_CMD_REG_RPU, .dfx_msg = &hclge_dbg_rpu_reg_1[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rpu_reg_1), .offset = HCLGE_DBG_DFX_RPU_1_OFFSET, .cmd = HCLGE_OPC_DFX_RPU_REG_1 } }, - { .reg_type = "ncsi", + { .cmd = HNAE3_DBG_CMD_REG_NCSI, .dfx_msg = &hclge_dbg_ncsi_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ncsi_reg), .offset = HCLGE_DBG_DFX_NCSI_OFFSET, .cmd = HCLGE_OPC_DFX_NCSI_REG } }, - { .reg_type = "rtc", + { .cmd = HNAE3_DBG_CMD_REG_RTC, .dfx_msg = &hclge_dbg_rtc_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rtc_reg), .offset = HCLGE_DBG_DFX_RTC_OFFSET, .cmd = HCLGE_OPC_DFX_RTC_REG } }, - { .reg_type = "ppp", + { .cmd = HNAE3_DBG_CMD_REG_PPP, .dfx_msg = &hclge_dbg_ppp_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ppp_reg), .offset = HCLGE_DBG_DFX_PPP_OFFSET, .cmd = HCLGE_OPC_DFX_PPP_REG } }, - { .reg_type = "rcb", + { .cmd = HNAE3_DBG_CMD_REG_RCB, .dfx_msg = &hclge_dbg_rcb_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rcb_reg), .offset = HCLGE_DBG_DFX_RCB_OFFSET, .cmd = HCLGE_OPC_DFX_RCB_REG } }, - { .reg_type = "tqp", + { .cmd = HNAE3_DBG_CMD_REG_TQP, .dfx_msg = &hclge_dbg_tqp_reg[0], .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_tqp_reg), .offset = HCLGE_DBG_DFX_TQP_OFFSET, @@ -106,7 +106,8 @@ static char *hclge_dbg_get_func_id_str(char *buf, u8 id) return buf; }
-static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset) +static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset, + u32 *bd_num) { struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; int entries_per_desc; @@ -116,13 +117,21 @@ static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset) ret = hclge_query_bd_num_cmd_send(hdev, desc); if (ret) { dev_err(&hdev->pdev->dev, - "get dfx bdnum fail, ret = %d\n", ret); + "failed to get dfx bd_num, offset = %d, ret = %d\n", + offset, ret); return ret; }
entries_per_desc = ARRAY_SIZE(desc[0].data); index = offset % entries_per_desc; - return le32_to_cpu(desc[offset / entries_per_desc].data[index]); + + *bd_num = le32_to_cpu(desc[offset / entries_per_desc].data[index]); + if (!(*bd_num)) { + dev_err(&hdev->pdev->dev, "The value of dfx bd_num is 0!\n"); + return -EINVAL; + } + + return 0; }
static int hclge_dbg_cmd_send(struct hclge_dev *hdev, @@ -149,66 +158,108 @@ static int hclge_dbg_cmd_send(struct hclge_dev *hdev, return ret; }
-static void hclge_dbg_dump_reg_common(struct hclge_dev *hdev, - const struct hclge_dbg_reg_type_info *reg_info, - const char *cmd_buf) +static int +hclge_dbg_dump_reg_tqp(struct hclge_dev *hdev, + const struct hclge_dbg_reg_type_info *reg_info, + char *buf, int len, int *pos) { -#define IDX_OFFSET 1 - - const char *s = &cmd_buf[strlen(reg_info->reg_type) + IDX_OFFSET]; const struct hclge_dbg_dfx_message *dfx_message = reg_info->dfx_msg; const struct hclge_dbg_reg_common_msg *reg_msg = ®_info->reg_msg; struct hclge_desc *desc_src; + u32 index, entry, i, cnt; + int bd_num, min_num, ret; struct hclge_desc *desc; - int entries_per_desc; - int bd_num, buf_len; - int index = 0; - int min_num; - int ret, i;
- if (*s) { - ret = kstrtouint(s, 0, &index); - index = (ret != 0) ? 0 : index; - } + ret = hclge_dbg_get_dfx_bd_num(hdev, reg_msg->offset, &bd_num); + if (ret) + return ret;
- bd_num = hclge_dbg_get_dfx_bd_num(hdev, reg_msg->offset); - if (bd_num <= 0) { - dev_err(&hdev->pdev->dev, "get cmd(%d) bd num(%d) failed\n", - reg_msg->offset, bd_num); - return; + desc_src = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL); + if (!desc_src) + return -ENOMEM; + + min_num = min_t(int, bd_num * HCLGE_DESC_DATA_LEN, reg_msg->msg_num); + + for (i = 0, cnt = 0; i < min_num; i++, dfx_message++) + *pos += scnprintf(buf + *pos, len - *pos, "item%u = %s\n", + cnt++, dfx_message->message); + + for (i = 0; i < cnt; i++) + *pos += scnprintf(buf + *pos, len - *pos, "item%u\t", i); + + *pos += scnprintf(buf + *pos, len - *pos, "\n"); + + for (index = 0; index < hdev->vport[0].alloc_tqps; index++) { + dfx_message = reg_info->dfx_msg; + desc = desc_src; + ret = hclge_dbg_cmd_send(hdev, desc, index, bd_num, + reg_msg->cmd); + if (ret) + break; + + for (i = 0; i < min_num; i++, dfx_message++) { + entry = i % HCLGE_DESC_DATA_LEN; + if (i > 0 && !entry) + desc++; + + *pos += scnprintf(buf + *pos, len - *pos, "%#x\t", + le32_to_cpu(desc->data[entry])); + } + *pos += scnprintf(buf + *pos, len - *pos, "\n"); }
- buf_len = sizeof(struct hclge_desc) * bd_num; - desc_src = kzalloc(buf_len, GFP_KERNEL); + kfree(desc_src); + return ret; +} + +static int +hclge_dbg_dump_reg_common(struct hclge_dev *hdev, + const struct hclge_dbg_reg_type_info *reg_info, + char *buf, int len, int *pos) +{ + const struct hclge_dbg_reg_common_msg *reg_msg = ®_info->reg_msg; + const struct hclge_dbg_dfx_message *dfx_message = reg_info->dfx_msg; + struct hclge_desc *desc_src; + int bd_num, min_num, ret; + struct hclge_desc *desc; + u32 entry, i; + + ret = hclge_dbg_get_dfx_bd_num(hdev, reg_msg->offset, &bd_num); + if (ret) + return ret; + + desc_src = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL); if (!desc_src) - return; + return -ENOMEM;
desc = desc_src; - ret = hclge_dbg_cmd_send(hdev, desc, index, bd_num, reg_msg->cmd); + + ret = hclge_dbg_cmd_send(hdev, desc, 0, bd_num, reg_msg->cmd); if (ret) { - kfree(desc_src); - return; + kfree(desc); + return ret; }
- entries_per_desc = ARRAY_SIZE(desc->data); - min_num = min_t(int, bd_num * entries_per_desc, reg_msg->msg_num); + min_num = min_t(int, bd_num * HCLGE_DESC_DATA_LEN, reg_msg->msg_num);
- desc = desc_src; - for (i = 0; i < min_num; i++) { - if (i > 0 && (i % entries_per_desc) == 0) + for (i = 0; i < min_num; i++, dfx_message++) { + entry = i % HCLGE_DESC_DATA_LEN; + if (i > 0 && !entry) desc++; - if (dfx_message->flag) - dev_info(&hdev->pdev->dev, "%s: 0x%x\n", - dfx_message->message, - le32_to_cpu(desc->data[i % entries_per_desc])); + if (!dfx_message->flag) + continue;
- dfx_message++; + *pos += scnprintf(buf + *pos, len - *pos, "%s: %#x\n", + dfx_message->message, + le32_to_cpu(desc->data[entry])); }
kfree(desc_src); + return 0; }
-static void hclge_dbg_dump_mac_enable_status(struct hclge_dev *hdev) +static int hclge_dbg_dump_mac_enable_status(struct hclge_dev *hdev, char *buf, + int len, int *pos) { struct hclge_config_mac_mode_cmd *req; struct hclge_desc desc; @@ -221,43 +272,51 @@ static void hclge_dbg_dump_mac_enable_status(struct hclge_dev *hdev) if (ret) { dev_err(&hdev->pdev->dev, "failed to dump mac enable status, ret = %d\n", ret); - return; + return ret; }
req = (struct hclge_config_mac_mode_cmd *)desc.data; loop_en = le32_to_cpu(req->txrx_pad_fcs_loop_en);
- dev_info(&hdev->pdev->dev, "config_mac_trans_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_TX_EN_B)); - dev_info(&hdev->pdev->dev, "config_mac_rcv_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_RX_EN_B)); - dev_info(&hdev->pdev->dev, "config_pad_trans_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_PAD_TX_B)); - dev_info(&hdev->pdev->dev, "config_pad_rcv_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_PAD_RX_B)); - dev_info(&hdev->pdev->dev, "config_1588_trans_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_1588_TX_B)); - dev_info(&hdev->pdev->dev, "config_1588_rcv_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_1588_RX_B)); - dev_info(&hdev->pdev->dev, "config_mac_app_loop_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_APP_LP_B)); - dev_info(&hdev->pdev->dev, "config_mac_line_loop_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_LINE_LP_B)); - dev_info(&hdev->pdev->dev, "config_mac_fcs_tx_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_FCS_TX_B)); - dev_info(&hdev->pdev->dev, "config_mac_rx_oversize_truncate_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B)); - dev_info(&hdev->pdev->dev, "config_mac_rx_fcs_strip_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_RX_FCS_STRIP_B)); - dev_info(&hdev->pdev->dev, "config_mac_rx_fcs_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_RX_FCS_B)); - dev_info(&hdev->pdev->dev, "config_mac_tx_under_min_err_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_TX_UNDER_MIN_ERR_B)); - dev_info(&hdev->pdev->dev, "config_mac_tx_oversize_truncate_en: %#x\n", - hnae3_get_bit(loop_en, HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_trans_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_TX_EN_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_rcv_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_RX_EN_B)); + *pos += scnprintf(buf + *pos, len - *pos, "pad_trans_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_PAD_TX_B)); + *pos += scnprintf(buf + *pos, len - *pos, "pad_rcv_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_PAD_RX_B)); + *pos += scnprintf(buf + *pos, len - *pos, "1588_trans_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_1588_TX_B)); + *pos += scnprintf(buf + *pos, len - *pos, "1588_rcv_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_1588_RX_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_app_loop_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_APP_LP_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_line_loop_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_LINE_LP_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_fcs_tx_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_FCS_TX_B)); + *pos += scnprintf(buf + *pos, len - *pos, + "mac_rx_oversize_truncate_en: %#x\n", + hnae3_get_bit(loop_en, + HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_rx_fcs_strip_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_RX_FCS_STRIP_B)); + *pos += scnprintf(buf + *pos, len - *pos, "mac_rx_fcs_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_RX_FCS_B)); + *pos += scnprintf(buf + *pos, len - *pos, + "mac_tx_under_min_err_en: %#x\n", + hnae3_get_bit(loop_en, HCLGE_MAC_TX_UNDER_MIN_ERR_B)); + *pos += scnprintf(buf + *pos, len - *pos, + "mac_tx_oversize_truncate_en: %#x\n", + hnae3_get_bit(loop_en, + HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B)); + + return 0; }
-static void hclge_dbg_dump_mac_frame_size(struct hclge_dev *hdev) +static int hclge_dbg_dump_mac_frame_size(struct hclge_dev *hdev, char *buf, + int len, int *pos) { struct hclge_config_max_frm_size_cmd *req; struct hclge_desc desc; @@ -269,17 +328,21 @@ static void hclge_dbg_dump_mac_frame_size(struct hclge_dev *hdev) if (ret) { dev_err(&hdev->pdev->dev, "failed to dump mac frame size, ret = %d\n", ret); - return; + return ret; }
req = (struct hclge_config_max_frm_size_cmd *)desc.data;
- dev_info(&hdev->pdev->dev, "max_frame_size: %u\n", - le16_to_cpu(req->max_frm_size)); - dev_info(&hdev->pdev->dev, "min_frame_size: %u\n", req->min_frm_size); + *pos += scnprintf(buf + *pos, len - *pos, "max_frame_size: %u\n", + le16_to_cpu(req->max_frm_size)); + *pos += scnprintf(buf + *pos, len - *pos, "min_frame_size: %u\n", + req->min_frm_size); + + return 0; }
-static void hclge_dbg_dump_mac_speed_duplex(struct hclge_dev *hdev) +static int hclge_dbg_dump_mac_speed_duplex(struct hclge_dev *hdev, char *buf, + int len, int *pos) { #define HCLGE_MAC_SPEED_SHIFT 0 #define HCLGE_MAC_SPEED_MASK GENMASK(5, 0) @@ -295,25 +358,34 @@ static void hclge_dbg_dump_mac_speed_duplex(struct hclge_dev *hdev) if (ret) { dev_err(&hdev->pdev->dev, "failed to dump mac speed duplex, ret = %d\n", ret); - return; + return ret; }
req = (struct hclge_config_mac_speed_dup_cmd *)desc.data;
- dev_info(&hdev->pdev->dev, "speed: %#lx\n", - hnae3_get_field(req->speed_dup, HCLGE_MAC_SPEED_MASK, - HCLGE_MAC_SPEED_SHIFT)); - dev_info(&hdev->pdev->dev, "duplex: %#x\n", - hnae3_get_bit(req->speed_dup, HCLGE_MAC_DUPLEX_SHIFT)); + *pos += scnprintf(buf + *pos, len - *pos, "speed: %#lx\n", + hnae3_get_field(req->speed_dup, HCLGE_MAC_SPEED_MASK, + HCLGE_MAC_SPEED_SHIFT)); + *pos += scnprintf(buf + *pos, len - *pos, "duplex: %#x\n", + hnae3_get_bit(req->speed_dup, + HCLGE_MAC_DUPLEX_SHIFT)); + return 0; }
-static void hclge_dbg_dump_mac(struct hclge_dev *hdev) +static int hclge_dbg_dump_mac(struct hclge_dev *hdev, char *buf, int len) { - hclge_dbg_dump_mac_enable_status(hdev); + int pos = 0; + int ret; + + ret = hclge_dbg_dump_mac_enable_status(hdev, buf, len, &pos); + if (ret) + return ret;
- hclge_dbg_dump_mac_frame_size(hdev); + ret = hclge_dbg_dump_mac_frame_size(hdev, buf, len, &pos); + if (ret) + return ret;
- hclge_dbg_dump_mac_speed_duplex(hdev); + return hclge_dbg_dump_mac_speed_duplex(hdev, buf, len, &pos); }
static void hclge_dbg_dump_dcb(struct hclge_dev *hdev, const char *cmd_buf) @@ -432,35 +504,28 @@ static void hclge_dbg_dump_dcb(struct hclge_dev *hdev, const char *cmd_buf) cmd, ret); }
-static void hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, const char *cmd_buf) +static int hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, + enum hnae3_dbg_cmd cmd, char *buf, int len) { const struct hclge_dbg_reg_type_info *reg_info; - bool has_dump = false; + int pos = 0, ret = 0; int i;
for (i = 0; i < ARRAY_SIZE(hclge_dbg_reg_info); i++) { reg_info = &hclge_dbg_reg_info[i]; - if (!strncmp(cmd_buf, reg_info->reg_type, - strlen(reg_info->reg_type))) { - hclge_dbg_dump_reg_common(hdev, reg_info, cmd_buf); - has_dump = true; + if (cmd == reg_info->cmd) { + if (cmd == HNAE3_DBG_CMD_REG_TQP) + return hclge_dbg_dump_reg_tqp(hdev, reg_info, + buf, len, &pos); + + ret = hclge_dbg_dump_reg_common(hdev, reg_info, buf, + len, &pos); + if (ret) + break; } }
- if (strncmp(cmd_buf, "mac", strlen("mac")) == 0) { - hclge_dbg_dump_mac(hdev); - has_dump = true; - } - - if (strncmp(cmd_buf, "dcb", 3) == 0) { - hclge_dbg_dump_dcb(hdev, &cmd_buf[sizeof("dcb")]); - has_dump = true; - } - - if (!has_dump) { - dev_info(&hdev->pdev->dev, "unknown command\n"); - return; - } + return ret; }
static void hclge_print_tc_info(struct hclge_dev *hdev, bool flag, int index) @@ -1807,7 +1872,7 @@ static int hclge_dbg_dump_mac_mc(struct hclge_dev *hdev, char *buf, int len)
int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { -#define DUMP_REG "dump reg" +#define DUMP_REG_DCB "dump reg dcb" #define DUMP_TM_MAP "dump tm map"
struct hclge_vport *vport = hclge_get_vport(handle); @@ -1827,8 +1892,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_qos_pri_map(hdev); } else if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { hclge_dbg_dump_qos_buf_cfg(hdev); - } else if (strncmp(cmd_buf, DUMP_REG, strlen(DUMP_REG)) == 0) { - hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]); + } else if (strncmp(cmd_buf, DUMP_REG_DCB, strlen(DUMP_REG_DCB)) == 0) { + hclge_dbg_dump_dcb(hdev, &cmd_buf[sizeof(DUMP_REG_DCB)]); } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { @@ -1889,18 +1954,65 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_NCL_CONFIG, .dbg_dump = hclge_dbg_dump_ncl_config, }, + { + .cmd = HNAE3_DBG_CMD_REG_BIOS_COMMON, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_SSU, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_IGU_EGU, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_RPU, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_NCSI, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_RTC, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_PPP, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_RCB, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_TQP, + .dbg_dump_reg = hclge_dbg_dump_reg_cmd, + }, + { + .cmd = HNAE3_DBG_CMD_REG_MAC, + .dbg_dump = hclge_dbg_dump_mac, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len) { struct hclge_vport *vport = hclge_get_vport(handle); + const struct hclge_dbg_func *cmd_func; struct hclge_dev *hdev = vport->back; u32 i;
for (i = 0; i < ARRAY_SIZE(hclge_dbg_cmd_func); i++) { - if (cmd == hclge_dbg_cmd_func[i].cmd) - return hclge_dbg_cmd_func[i].dbg_dump(hdev, buf, len); + if (cmd == hclge_dbg_cmd_func[i].cmd) { + cmd_func = &hclge_dbg_cmd_func[i]; + if (cmd_func->dbg_dump) + return cmd_func->dbg_dump(hdev, buf, len); + else + return cmd_func->dbg_dump_reg(hdev, cmd, buf, + len); + } }
dev_err(&hdev->pdev->dev, "invalid command(%d)\n", cmd); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index bf6a0ff66047..933f157294fd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -77,7 +77,7 @@ struct hclge_dbg_dfx_message {
#define HCLGE_DBG_MAC_REG_TYPE_LEN 32 struct hclge_dbg_reg_type_info { - const char *reg_type; + enum hnae3_dbg_cmd cmd; const struct hclge_dbg_dfx_message *dfx_msg; struct hclge_dbg_reg_common_msg reg_msg; }; @@ -85,6 +85,8 @@ struct hclge_dbg_reg_type_info { struct hclge_dbg_func { enum hnae3_dbg_cmd cmd; int (*dbg_dump)(struct hclge_dev *hdev, char *buf, int len); + int (*dbg_dump_reg)(struct hclge_dev *hdev, enum hnae3_dbg_cmd cmd, + char *buf, int len); };
static const struct hclge_dbg_dfx_message hclge_dbg_bios_common_reg[] = {
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit 365e860aa7a74afe1ba7157b3bfc547551c5795e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for reg dcb info is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "dcb" for it, and query it by command "cat dcb", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat dcb qset_id roce_qset_mask nic_qset_mask qset_shaping_pass qset_bp_status 0000 0x1 0x1 0x1 0x0 0001 0x1 0x1 0x1 0x0 0002 0x1 0x1 0x1 0x0 0003 0x1 0x1 0x1 0x0 0004 0x1 0x1 0x1 0x0 0005 0x1 0x1 0x1 0x0 0006 0x1 0x1 0x1 0x0 0007 0x1 0x1 0x1 0x0 pri_id pri_mask pri_cshaping_pass pri_pshaping_pass 000 0x1 0x0 0x1 001 0x1 0x0 0x0 002 0x1 0x0 0x0 003 0x1 0x0 0x0 004 0x1 0x0 0x0 005 0x1 0x0 0x0 006 0x1 0x0 0x0 007 0x1 0x0 0x0 pg_id pg_mask pg_cshaping_pass pg_pshaping_pass 000 0x1 0x0 0x1
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 18 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 296 ++++++++++++------ 3 files changed, 215 insertions(+), 100 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 2a7de739b2ee..747670b77fd2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -274,6 +274,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_REG_RCB, HNAE3_DBG_CMD_REG_TQP, HNAE3_DBG_CMD_REG_MAC, + HNAE3_DBG_CMD_REG_DCB, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index af0751e53f79..9add38948e98 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -205,6 +205,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "dcb", + .cmd = HNAE3_DBG_CMD_REG_DCB, + .dentry = HNS3_DBG_DENTRY_REG, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -581,10 +588,6 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len)
static void hns3_dbg_help(struct hnae3_handle *h) { -#define HNS3_DBG_BUF_LEN 256 - - char printf_buf[HNS3_DBG_BUF_LEN]; - dev_info(&h->pdev->dev, "available commands\n"); dev_info(&h->pdev->dev, "queue info <number>\n"); dev_info(&h->pdev->dev, "queue map\n"); @@ -601,13 +604,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump qos buf cfg\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); - - memset(printf_buf, 0, HNS3_DBG_BUF_LEN); - strncat(printf_buf, "dump reg dcb <port_id> <pri_id> <pg_id>", - HNS3_DBG_BUF_LEN - 1); - strncat(printf_buf + strlen(printf_buf), " <rq_id> <nq_id> <qset_id>\n", - HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); - dev_info(&h->pdev->dev, "%s", printf_buf); }
static void diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 2f6662892edc..1ad7bffb4d62 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -388,120 +388,237 @@ static int hclge_dbg_dump_mac(struct hclge_dev *hdev, char *buf, int len) return hclge_dbg_dump_mac_speed_duplex(hdev, buf, len, &pos); }
-static void hclge_dbg_dump_dcb(struct hclge_dev *hdev, const char *cmd_buf) +static int hclge_dbg_dump_dcb_qset(struct hclge_dev *hdev, char *buf, int len, + int *pos) { - struct device *dev = &hdev->pdev->dev; struct hclge_dbg_bitmap_cmd *bitmap; - enum hclge_opcode_type cmd; - int rq_id, pri_id, qset_id; - int port_id, nq_id, pg_id; - struct hclge_desc desc[2]; + struct hclge_desc desc; + u16 qset_id, qset_num; + int ret; + + ret = hclge_tm_get_qset_num(hdev, &qset_num); + if (ret) + return ret;
- int cnt, ret; + *pos += scnprintf(buf + *pos, len - *pos, + "qset_id roce_qset_mask nic_qset_mask qset_shaping_pass qset_bp_status\n"); + for (qset_id = 0; qset_id < qset_num; qset_id++) { + ret = hclge_dbg_cmd_send(hdev, &desc, qset_id, 1, + HCLGE_OPC_QSET_DFX_STS); + if (ret) + return ret;
- cnt = sscanf(cmd_buf, "%i %i %i %i %i %i", - &port_id, &pri_id, &pg_id, &rq_id, &nq_id, &qset_id); - if (cnt != 6) { - dev_err(&hdev->pdev->dev, - "dump dcb: bad command parameter, cnt=%d\n", cnt); - return; + bitmap = (struct hclge_dbg_bitmap_cmd *)&desc.data[1]; + + *pos += scnprintf(buf + *pos, len - *pos, + "%04u %#x %#x %#x %#x\n", + qset_id, bitmap->bit0, bitmap->bit1, + bitmap->bit2, bitmap->bit3); }
- cmd = HCLGE_OPC_QSET_DFX_STS; - ret = hclge_dbg_cmd_send(hdev, desc, qset_id, 1, cmd); - if (ret) - goto err_dcb_cmd_send; + return 0; +}
- bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1]; - dev_info(dev, "roce_qset_mask: 0x%x\n", bitmap->bit0); - dev_info(dev, "nic_qs_mask: 0x%x\n", bitmap->bit1); - dev_info(dev, "qs_shaping_pass: 0x%x\n", bitmap->bit2); - dev_info(dev, "qs_bp_sts: 0x%x\n", bitmap->bit3); +static int hclge_dbg_dump_dcb_pri(struct hclge_dev *hdev, char *buf, int len, + int *pos) +{ + struct hclge_dbg_bitmap_cmd *bitmap; + struct hclge_desc desc; + u8 pri_id, pri_num; + int ret;
- cmd = HCLGE_OPC_PRI_DFX_STS; - ret = hclge_dbg_cmd_send(hdev, desc, pri_id, 1, cmd); + ret = hclge_tm_get_pri_num(hdev, &pri_num); if (ret) - goto err_dcb_cmd_send; + return ret;
- bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1]; - dev_info(dev, "pri_mask: 0x%x\n", bitmap->bit0); - dev_info(dev, "pri_cshaping_pass: 0x%x\n", bitmap->bit1); - dev_info(dev, "pri_pshaping_pass: 0x%x\n", bitmap->bit2); + *pos += scnprintf(buf + *pos, len - *pos, + "pri_id pri_mask pri_cshaping_pass pri_pshaping_pass\n"); + for (pri_id = 0; pri_id < pri_num; pri_id++) { + ret = hclge_dbg_cmd_send(hdev, &desc, pri_id, 1, + HCLGE_OPC_PRI_DFX_STS); + if (ret) + return ret;
- cmd = HCLGE_OPC_PG_DFX_STS; - ret = hclge_dbg_cmd_send(hdev, desc, pg_id, 1, cmd); - if (ret) - goto err_dcb_cmd_send; + bitmap = (struct hclge_dbg_bitmap_cmd *)&desc.data[1]; + + *pos += scnprintf(buf + *pos, len - *pos, + "%03u %#x %#x %#x\n", + pri_id, bitmap->bit0, bitmap->bit1, + bitmap->bit2); + } + + return 0; +} + +static int hclge_dbg_dump_dcb_pg(struct hclge_dev *hdev, char *buf, int len, + int *pos) +{ + struct hclge_dbg_bitmap_cmd *bitmap; + struct hclge_desc desc; + u8 pg_id; + int ret; + + *pos += scnprintf(buf + *pos, len - *pos, + "pg_id pg_mask pg_cshaping_pass pg_pshaping_pass\n"); + for (pg_id = 0; pg_id < hdev->tm_info.num_pg; pg_id++) { + ret = hclge_dbg_cmd_send(hdev, &desc, pg_id, 1, + HCLGE_OPC_PG_DFX_STS); + if (ret) + return ret; + + bitmap = (struct hclge_dbg_bitmap_cmd *)&desc.data[1]; + + *pos += scnprintf(buf + *pos, len - *pos, + "%03u %#x %#x %#x\n", + pg_id, bitmap->bit0, bitmap->bit1, + bitmap->bit2); + } + + return 0; +} + +static int hclge_dbg_dump_dcb_queue(struct hclge_dev *hdev, char *buf, int len, + int *pos) +{ + struct hclge_desc desc; + u16 nq_id; + int ret; + + *pos += scnprintf(buf + *pos, len - *pos, + "nq_id sch_nic_queue_cnt sch_roce_queue_cnt\n"); + for (nq_id = 0; nq_id < hdev->num_tqps; nq_id++) { + ret = hclge_dbg_cmd_send(hdev, &desc, nq_id, 1, + HCLGE_OPC_SCH_NQ_CNT); + if (ret) + return ret; + + *pos += scnprintf(buf + *pos, len - *pos, "%04u %#x", + nq_id, le32_to_cpu(desc.data[1])); + + ret = hclge_dbg_cmd_send(hdev, &desc, nq_id, 1, + HCLGE_OPC_SCH_RQ_CNT); + if (ret) + return ret; + + *pos += scnprintf(buf + *pos, len - *pos, + " %#x\n", + le32_to_cpu(desc.data[1])); + }
- bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1]; - dev_info(dev, "pg_mask: 0x%x\n", bitmap->bit0); - dev_info(dev, "pg_cshaping_pass: 0x%x\n", bitmap->bit1); - dev_info(dev, "pg_pshaping_pass: 0x%x\n", bitmap->bit2); + return 0; +}
- cmd = HCLGE_OPC_PORT_DFX_STS; - ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, cmd); +static int hclge_dbg_dump_dcb_port(struct hclge_dev *hdev, char *buf, int len, + int *pos) +{ + struct hclge_dbg_bitmap_cmd *bitmap; + struct hclge_desc desc; + u8 port_id = 0; + int ret; + + ret = hclge_dbg_cmd_send(hdev, &desc, port_id, 1, + HCLGE_OPC_PORT_DFX_STS); if (ret) - goto err_dcb_cmd_send; + return ret;
- bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1]; - dev_info(dev, "port_mask: 0x%x\n", bitmap->bit0); - dev_info(dev, "port_shaping_pass: 0x%x\n", bitmap->bit1); + bitmap = (struct hclge_dbg_bitmap_cmd *)&desc.data[1];
- cmd = HCLGE_OPC_SCH_NQ_CNT; - ret = hclge_dbg_cmd_send(hdev, desc, nq_id, 1, cmd); + *pos += scnprintf(buf + *pos, len - *pos, "port_mask: %#x\n", + bitmap->bit0); + *pos += scnprintf(buf + *pos, len - *pos, "port_shaping_pass: %#x\n", + bitmap->bit1); + + return 0; +} + +static int hclge_dbg_dump_dcb_tm(struct hclge_dev *hdev, char *buf, int len, + int *pos) +{ + struct hclge_desc desc[2]; + u8 port_id = 0; + int ret; + + ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, + HCLGE_OPC_TM_INTERNAL_CNT); if (ret) - goto err_dcb_cmd_send; + return ret;
- dev_info(dev, "sch_nq_cnt: 0x%x\n", le32_to_cpu(desc[0].data[1])); + *pos += scnprintf(buf + *pos, len - *pos, "SCH_NIC_NUM: %#x\n", + le32_to_cpu(desc[0].data[1])); + *pos += scnprintf(buf + *pos, len - *pos, "SCH_ROCE_NUM: %#x\n", + le32_to_cpu(desc[0].data[2]));
- cmd = HCLGE_OPC_SCH_RQ_CNT; - ret = hclge_dbg_cmd_send(hdev, desc, nq_id, 1, cmd); + ret = hclge_dbg_cmd_send(hdev, desc, port_id, 2, + HCLGE_OPC_TM_INTERNAL_STS); if (ret) - goto err_dcb_cmd_send; + return ret;
- dev_info(dev, "sch_rq_cnt: 0x%x\n", le32_to_cpu(desc[0].data[1])); + *pos += scnprintf(buf + *pos, len - *pos, "pri_bp: %#x\n", + le32_to_cpu(desc[0].data[1])); + *pos += scnprintf(buf + *pos, len - *pos, "fifo_dfx_info: %#x\n", + le32_to_cpu(desc[0].data[2])); + *pos += scnprintf(buf + *pos, len - *pos, + "sch_roce_fifo_afull_gap: %#x\n", + le32_to_cpu(desc[0].data[3])); + *pos += scnprintf(buf + *pos, len - *pos, + "tx_private_waterline: %#x\n", + le32_to_cpu(desc[0].data[4])); + *pos += scnprintf(buf + *pos, len - *pos, "tm_bypass_en: %#x\n", + le32_to_cpu(desc[0].data[5])); + *pos += scnprintf(buf + *pos, len - *pos, "SSU_TM_BYPASS_EN: %#x\n", + le32_to_cpu(desc[1].data[0])); + *pos += scnprintf(buf + *pos, len - *pos, "SSU_RESERVE_CFG: %#x\n", + le32_to_cpu(desc[1].data[1])); + + if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) + return 0; + + ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, + HCLGE_OPC_TM_INTERNAL_STS_1); + if (ret) + return ret; + + *pos += scnprintf(buf + *pos, len - *pos, "TC_MAP_SEL: %#x\n", + le32_to_cpu(desc[0].data[1])); + *pos += scnprintf(buf + *pos, len - *pos, "IGU_PFC_PRI_EN: %#x\n", + le32_to_cpu(desc[0].data[2])); + *pos += scnprintf(buf + *pos, len - *pos, "MAC_PFC_PRI_EN: %#x\n", + le32_to_cpu(desc[0].data[3])); + *pos += scnprintf(buf + *pos, len - *pos, "IGU_PRI_MAP_TC_CFG: %#x\n", + le32_to_cpu(desc[0].data[4])); + *pos += scnprintf(buf + *pos, len - *pos, + "IGU_TX_PRI_MAP_TC_CFG: %#x\n", + le32_to_cpu(desc[0].data[5])); + + return 0; +} + +static int hclge_dbg_dump_dcb(struct hclge_dev *hdev, char *buf, int len) +{ + int pos = 0; + int ret; + + ret = hclge_dbg_dump_dcb_qset(hdev, buf, len, &pos); + if (ret) + return ret;
- cmd = HCLGE_OPC_TM_INTERNAL_STS; - ret = hclge_dbg_cmd_send(hdev, desc, 0, 2, cmd); + ret = hclge_dbg_dump_dcb_pri(hdev, buf, len, &pos); if (ret) - goto err_dcb_cmd_send; - - dev_info(dev, "pri_bp: 0x%x\n", le32_to_cpu(desc[0].data[1])); - dev_info(dev, "fifo_dfx_info: 0x%x\n", le32_to_cpu(desc[0].data[2])); - dev_info(dev, "sch_roce_fifo_afull_gap: 0x%x\n", - le32_to_cpu(desc[0].data[3])); - dev_info(dev, "tx_private_waterline: 0x%x\n", - le32_to_cpu(desc[0].data[4])); - dev_info(dev, "tm_bypass_en: 0x%x\n", le32_to_cpu(desc[0].data[5])); - dev_info(dev, "SSU_TM_BYPASS_EN: 0x%x\n", le32_to_cpu(desc[1].data[0])); - dev_info(dev, "SSU_RESERVE_CFG: 0x%x\n", le32_to_cpu(desc[1].data[1])); - - cmd = HCLGE_OPC_TM_INTERNAL_CNT; - ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, cmd); + return ret; + + ret = hclge_dbg_dump_dcb_pg(hdev, buf, len, &pos); if (ret) - goto err_dcb_cmd_send; + return ret;
- dev_info(dev, "SCH_NIC_NUM: 0x%x\n", le32_to_cpu(desc[0].data[1])); - dev_info(dev, "SCH_ROCE_NUM: 0x%x\n", le32_to_cpu(desc[0].data[2])); + ret = hclge_dbg_dump_dcb_queue(hdev, buf, len, &pos); + if (ret) + return ret;
- cmd = HCLGE_OPC_TM_INTERNAL_STS_1; - ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, cmd); + ret = hclge_dbg_dump_dcb_port(hdev, buf, len, &pos); if (ret) - goto err_dcb_cmd_send; - - dev_info(dev, "TC_MAP_SEL: 0x%x\n", le32_to_cpu(desc[0].data[1])); - dev_info(dev, "IGU_PFC_PRI_EN: 0x%x\n", le32_to_cpu(desc[0].data[2])); - dev_info(dev, "MAC_PFC_PRI_EN: 0x%x\n", le32_to_cpu(desc[0].data[3])); - dev_info(dev, "IGU_PRI_MAP_TC_CFG: 0x%x\n", - le32_to_cpu(desc[0].data[4])); - dev_info(dev, "IGU_TX_PRI_MAP_TC_CFG: 0x%x\n", - le32_to_cpu(desc[0].data[5])); - return; + return ret;
-err_dcb_cmd_send: - dev_err(&hdev->pdev->dev, - "failed to dump dcb dfx, cmd = %#x, ret = %d\n", - cmd, ret); + return hclge_dbg_dump_dcb_tm(hdev, buf, len, &pos); }
static int hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, @@ -1872,7 +1989,6 @@ static int hclge_dbg_dump_mac_mc(struct hclge_dev *hdev, char *buf, int len)
int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { -#define DUMP_REG_DCB "dump reg dcb" #define DUMP_TM_MAP "dump tm map"
struct hclge_vport *vport = hclge_get_vport(handle); @@ -1892,8 +2008,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_qos_pri_map(hdev); } else if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { hclge_dbg_dump_qos_buf_cfg(hdev); - } else if (strncmp(cmd_buf, DUMP_REG_DCB, strlen(DUMP_REG_DCB)) == 0) { - hclge_dbg_dump_dcb(hdev, &cmd_buf[sizeof(DUMP_REG_DCB)]); } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { @@ -1994,6 +2108,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_REG_MAC, .dbg_dump = hclge_dbg_dump_mac, }, + { + .cmd = HNAE3_DBG_CMD_REG_DCB, + .dbg_dump = hclge_dbg_dump_dcb, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,
From: Hao Chen chenhao288@hisilicon.com
mainline inclusion from mainline-master commit d2f737cf21b87d4239987da69a3b14730c6a57ad category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for queue map is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "queue_map" for it, and query it by command "cat queue_map", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat queue_map local_queue_id global_queue_id vector_id 0 0 341
Signed-off-by: Hao Chen chenhao288@hisilicon.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 58 ++++++++++++++----- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 1 + 3 files changed, 45 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 747670b77fd2..b5ebb29d9c9c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -275,6 +275,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_REG_TQP, HNAE3_DBG_CMD_REG_MAC, HNAE3_DBG_CMD_REG_DCB, + HNAE3_DBG_CMD_QUEUE_MAP, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 9add38948e98..fc4e17b6d86f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -26,6 +26,9 @@ static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { { .name = "reg" }, + { + .name = "queue" + }, /* keep common at the bottom and add new directory above */ { .name = "common" @@ -212,6 +215,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "queue_map", + .cmd = HNAE3_DBG_CMD_QUEUE_MAP, + .dentry = HNS3_DBG_DENTRY_QUEUE, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -403,27 +413,44 @@ static int hns3_dbg_queue_info(struct hnae3_handle *h, return 0; }
-static int hns3_dbg_queue_map(struct hnae3_handle *h) +static const struct hns3_dbg_item queue_map_items[] = { + { "local_queue_id", 2 }, + { "global_queue_id", 2 }, + { "vector_id", 2 }, +}; + +static int hns3_dbg_queue_map(struct hnae3_handle *h, char *buf, int len) { + char data_str[ARRAY_SIZE(queue_map_items)][HNS3_DBG_DATA_STR_LEN]; + char *result[ARRAY_SIZE(queue_map_items)]; struct hns3_nic_priv *priv = h->priv; - int i; + char content[HNS3_DBG_INFO_LEN]; + int pos = 0; + int j; + u32 i;
if (!h->ae_algo->ops->get_global_queue_id) return -EOPNOTSUPP;
- dev_info(&h->pdev->dev, "map info for queue id and vector id\n"); - dev_info(&h->pdev->dev, - "local queue id | global queue id | vector id\n"); - for (i = 0; i < h->kinfo.num_tqps; i++) { - u16 global_qid; + for (i = 0; i < ARRAY_SIZE(queue_map_items); i++) + result[i] = &data_str[i][0];
- global_qid = h->ae_algo->ops->get_global_queue_id(h, i); + hns3_dbg_fill_content(content, sizeof(content), queue_map_items, + NULL, ARRAY_SIZE(queue_map_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + for (i = 0; i < h->kinfo.num_tqps; i++) { if (!priv->ring || !priv->ring[i].tqp_vector) continue; - - dev_info(&h->pdev->dev, - " %4d %4u %4d\n", - i, global_qid, priv->ring[i].tqp_vector->vector_irq); + j = 0; + sprintf(result[j++], "%u", i); + sprintf(result[j++], "%u", + h->ae_algo->ops->get_global_queue_id(h, i)); + sprintf(result[j++], "%u", + priv->ring[i].tqp_vector->vector_irq); + hns3_dbg_fill_content(content, sizeof(content), queue_map_items, + (const char **)result, + ARRAY_SIZE(queue_map_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); }
return 0; @@ -590,7 +617,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) { dev_info(&h->pdev->dev, "available commands\n"); dev_info(&h->pdev->dev, "queue info <number>\n"); - dev_info(&h->pdev->dev, "queue map\n");
if (!hns3_is_phys_func(h->pdev)) return; @@ -717,8 +743,6 @@ static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf) hns3_dbg_help(handle); else if (strncmp(cmd_buf, "queue info", 10) == 0) ret = hns3_dbg_queue_info(handle, cmd_buf); - else if (strncmp(cmd_buf, "queue map", 9) == 0) - ret = hns3_dbg_queue_map(handle); else if (handle->ae_algo->ops->dbg_run_cmd) ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); else @@ -793,6 +817,10 @@ static int hns3_dbg_get_cmd_index(struct hnae3_handle *handle, }
static const struct hns3_dbg_func hns3_dbg_cmd_func[] = { + { + .cmd = HNAE3_DBG_CMD_QUEUE_MAP, + .dbg_dump = hns3_dbg_queue_map, + }, { .cmd = HNAE3_DBG_CMD_DEV_INFO, .dbg_dump = hns3_dbg_dev_info, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index 6060bfc21850..4cab37a5d44a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -30,6 +30,7 @@ enum hns3_dbg_dentry_type { HNS3_DBG_DENTRY_RX_BD, HNS3_DBG_DENTRY_MAC, HNS3_DBG_DENTRY_REG, + HNS3_DBG_DENTRY_QUEUE, HNS3_DBG_DENTRY_COMMON, };
From: Hao Chen chenhao288@hisilicon.com
mainline inclusion from mainline-master commit e44c495d95e0dd3a5513f72a830639a72b4c14f1 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for queue info is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create two files "rx_queue_info" and "tx_queue_info" for it, and query it by command "cat rx_queue_info" and "cat tx_queue_info", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat rx_queue_info QUEUE_ID BD_NUM BD_LEN TAIL HEAD FBDNUM PKTNUM ... 0 0 0 0 0 0 0 ... 1 0 0 0 0 0 0 ... 2 0 0 0 0 0 0 ...
$ cat tx_queue_info QUEUE_ID BD_NUM TC TAIL HEAD FBDNUM OFFSET PKTNUM ... 0 0 0 0 0 0 0 0 ... 1 0 0 0 0 0 0 0 ... 2 0 0 0 0 0 0 0 ...
Signed-off-by: Hao Chen chenhao288@hisilicon.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 294 ++++++++++++------ .../ethernet/hisilicon/hns3/hns3_debugfs.h | 1 + 3 files changed, 196 insertions(+), 101 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index b5ebb29d9c9c..b7116015bcdd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -276,6 +276,8 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_REG_MAC, HNAE3_DBG_CMD_REG_DCB, HNAE3_DBG_CMD_QUEUE_MAP, + HNAE3_DBG_CMD_RX_QUEUE_INFO, + HNAE3_DBG_CMD_TX_QUEUE_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index fc4e17b6d86f..93455c7ed59d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -222,6 +222,20 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "rx_queue_info", + .cmd = HNAE3_DBG_CMD_RX_QUEUE_INFO, + .dentry = HNS3_DBG_DENTRY_QUEUE, + .buf_len = HNS3_DBG_READ_LEN_1MB, + .init = hns3_dbg_common_file_init, + }, + { + .name = "tx_queue_info", + .cmd = HNAE3_DBG_CMD_TX_QUEUE_INFO, + .dentry = HNS3_DBG_DENTRY_QUEUE, + .buf_len = HNS3_DBG_READ_LEN_1MB, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -282,39 +296,86 @@ static void hns3_dbg_fill_content(char *content, u16 len, *pos++ = '\0'; }
-static int hns3_dbg_queue_info(struct hnae3_handle *h, - const char *cmd_buf) +static const struct hns3_dbg_item rx_queue_info_items[] = { + { "QUEUE_ID", 2 }, + { "BD_NUM", 2 }, + { "BD_LEN", 2 }, + { "TAIL", 2 }, + { "HEAD", 2 }, + { "FBDNUM", 2 }, + { "PKTNUM", 2 }, + { "RING_EN", 2 }, + { "RX_RING_EN", 2 }, + { "BASE_ADDR", 10 }, +}; + +static void hns3_dump_rx_queue_info(struct hns3_enet_ring *ring, + struct hnae3_ae_dev *ae_dev, char **result, + u32 index) { + u32 base_add_l, base_add_h; + u32 j = 0; + + sprintf(result[j++], "%8u", index); + + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_BD_NUM_REG)); + + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_BD_LEN_REG)); + + sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_TAIL_REG)); + + sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_HEAD_REG)); + + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_FBDNUM_REG)); + + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_PKTNUM_RECORD_REG)); + + sprintf(result[j++], "%7s", readl_relaxed(ring->tqp->io_base + + HNS3_RING_EN_REG) ? "on" : "off"); + + if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) + sprintf(result[j++], "%10s", readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_EN_REG) ? "on" : "off"); + else + sprintf(result[j++], "%10s", "NA"); + + base_add_h = readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_BASEADDR_H_REG); + base_add_l = readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_RING_BASEADDR_L_REG); + sprintf(result[j++], "0x%08x%08x", base_add_h, base_add_l); +} + +static int hns3_dbg_rx_queue_info(struct hnae3_handle *h, + char *buf, int len) +{ + char data_str[ARRAY_SIZE(rx_queue_info_items)][HNS3_DBG_DATA_STR_LEN]; struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); + char *result[ARRAY_SIZE(rx_queue_info_items)]; struct hns3_nic_priv *priv = h->priv; + char content[HNS3_DBG_INFO_LEN]; struct hns3_enet_ring *ring; - u32 base_add_l, base_add_h; - u32 queue_num, queue_max; - u32 value, i; - int cnt; + int pos = 0; + u32 i;
if (!priv->ring) { dev_err(&h->pdev->dev, "priv->ring is NULL\n"); return -EFAULT; }
- queue_max = h->kinfo.num_tqps; - cnt = kstrtouint(&cmd_buf[11], 0, &queue_num); - if (cnt) - queue_num = 0; - else - queue_max = queue_num + 1; - - dev_info(&h->pdev->dev, "queue info\n"); - - if (queue_num >= h->kinfo.num_tqps) { - dev_err(&h->pdev->dev, - "Queue number(%u) is out of range(0-%u)\n", queue_num, - h->kinfo.num_tqps - 1); - return -EINVAL; - } + for (i = 0; i < ARRAY_SIZE(rx_queue_info_items); i++) + result[i] = &data_str[i][0];
- for (i = queue_num; i < queue_max; i++) { + hns3_dbg_fill_content(content, sizeof(content), rx_queue_info_items, + NULL, ARRAY_SIZE(rx_queue_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + for (i = 0; i < h->kinfo.num_tqps; i++) { /* Each cycle needs to determine whether the instance is reset, * to prevent reference to invalid memory. And need to ensure * that the following code is executed within 100ms. @@ -324,90 +385,116 @@ static int hns3_dbg_queue_info(struct hnae3_handle *h, return -EPERM;
ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)]; - base_add_h = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_BASEADDR_H_REG); - base_add_l = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_BASEADDR_L_REG); - dev_info(&h->pdev->dev, "RX(%u) BASE ADD: 0x%08x%08x\n", i, - base_add_h, base_add_l); + hns3_dump_rx_queue_info(ring, ae_dev, result, i); + hns3_dbg_fill_content(content, sizeof(content), + rx_queue_info_items, + (const char **)result, + ARRAY_SIZE(rx_queue_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + } + + return 0; +} + +static const struct hns3_dbg_item tx_queue_info_items[] = { + { "QUEUE_ID", 2 }, + { "BD_NUM", 2 }, + { "TC", 2 }, + { "TAIL", 2 }, + { "HEAD", 2 }, + { "FBDNUM", 2 }, + { "OFFSET", 2 }, + { "PKTNUM", 2 }, + { "RING_EN", 2 }, + { "TX_RING_EN", 2 }, + { "BASE_ADDR", 10 }, +}; + +static void hns3_dump_tx_queue_info(struct hns3_enet_ring *ring, + struct hnae3_ae_dev *ae_dev, char **result, + u32 index) +{ + u32 base_add_l, base_add_h; + u32 j = 0;
- value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_BD_NUM_REG); - dev_info(&h->pdev->dev, "RX(%u) RING BD NUM: %u\n", i, value); + sprintf(result[j++], "%8u", index); + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_BD_NUM_REG));
- value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_BD_LEN_REG); - dev_info(&h->pdev->dev, "RX(%u) RING BD LEN: %u\n", i, value); + sprintf(result[j++], "%2u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_TC_REG));
- value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_TAIL_REG); - dev_info(&h->pdev->dev, "RX(%u) RING TAIL: %u\n", i, value); + sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_TAIL_REG));
- value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_HEAD_REG); - dev_info(&h->pdev->dev, "RX(%u) RING HEAD: %u\n", i, value); + sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_HEAD_REG));
- value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_FBDNUM_REG); - dev_info(&h->pdev->dev, "RX(%u) RING FBDNUM: %u\n", i, value); + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_FBDNUM_REG));
- value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_RING_PKTNUM_RECORD_REG); - dev_info(&h->pdev->dev, "RX(%u) RING PKTNUM: %u\n", i, value); + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_OFFSET_REG));
- ring = &priv->ring[i]; - base_add_h = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_BASEADDR_H_REG); - base_add_l = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_BASEADDR_L_REG); - dev_info(&h->pdev->dev, "TX(%u) BASE ADD: 0x%08x%08x\n", i, - base_add_h, base_add_l); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_BD_NUM_REG); - dev_info(&h->pdev->dev, "TX(%u) RING BD NUM: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_TC_REG); - dev_info(&h->pdev->dev, "TX(%u) RING TC: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_TAIL_REG); - dev_info(&h->pdev->dev, "TX(%u) RING TAIL: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_HEAD_REG); - dev_info(&h->pdev->dev, "TX(%u) RING HEAD: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_FBDNUM_REG); - dev_info(&h->pdev->dev, "TX(%u) RING FBDNUM: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_OFFSET_REG); - dev_info(&h->pdev->dev, "TX(%u) RING OFFSET: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_RING_PKTNUM_RECORD_REG); - dev_info(&h->pdev->dev, "TX(%u) RING PKTNUM: %u\n", i, value); - - value = readl_relaxed(ring->tqp->io_base + HNS3_RING_EN_REG); - dev_info(&h->pdev->dev, "TX/RX(%u) RING EN: %s\n", i, - value ? "enable" : "disable"); - - if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) { - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_EN_REG); - dev_info(&h->pdev->dev, "TX(%u) RING EN: %s\n", i, - value ? "enable" : "disable"); - - value = readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_EN_REG); - dev_info(&h->pdev->dev, "RX(%u) RING EN: %s\n", i, - value ? "enable" : "disable"); - } + sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_PKTNUM_RECORD_REG));
- dev_info(&h->pdev->dev, "\n"); + sprintf(result[j++], "%7s", readl_relaxed(ring->tqp->io_base + + HNS3_RING_EN_REG) ? "on" : "off"); + + if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) + sprintf(result[j++], "%10s", readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_EN_REG) ? "on" : "off"); + else + sprintf(result[j++], "%10s", "NA"); + + base_add_h = readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_BASEADDR_H_REG); + base_add_l = readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_RING_BASEADDR_L_REG); + sprintf(result[j++], "0x%08x%08x", base_add_h, base_add_l); +} + +static int hns3_dbg_tx_queue_info(struct hnae3_handle *h, + char *buf, int len) +{ + char data_str[ARRAY_SIZE(tx_queue_info_items)][HNS3_DBG_DATA_STR_LEN]; + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); + char *result[ARRAY_SIZE(tx_queue_info_items)]; + struct hns3_nic_priv *priv = h->priv; + char content[HNS3_DBG_INFO_LEN]; + struct hns3_enet_ring *ring; + int pos = 0; + u32 i; + + if (!priv->ring) { + dev_err(&h->pdev->dev, "priv->ring is NULL\n"); + return -EFAULT; + } + + for (i = 0; i < ARRAY_SIZE(tx_queue_info_items); i++) + result[i] = &data_str[i][0]; + + hns3_dbg_fill_content(content, sizeof(content), tx_queue_info_items, + NULL, ARRAY_SIZE(tx_queue_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); + + for (i = 0; i < h->kinfo.num_tqps; i++) { + /* Each cycle needs to determine whether the instance is reset, + * to prevent reference to invalid memory. And need to ensure + * that the following code is executed within 100ms. + */ + if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || + test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + return -EPERM; + + ring = &priv->ring[i]; + hns3_dump_tx_queue_info(ring, ae_dev, result, i); + hns3_dbg_fill_content(content, sizeof(content), + tx_queue_info_items, + (const char **)result, + ARRAY_SIZE(tx_queue_info_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); }
return 0; @@ -616,7 +703,6 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) static void hns3_dbg_help(struct hnae3_handle *h) { dev_info(&h->pdev->dev, "available commands\n"); - dev_info(&h->pdev->dev, "queue info <number>\n");
if (!hns3_is_phys_func(h->pdev)) return; @@ -741,8 +827,6 @@ static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf)
if (strncmp(cmd_buf, "help", 4) == 0) hns3_dbg_help(handle); - else if (strncmp(cmd_buf, "queue info", 10) == 0) - ret = hns3_dbg_queue_info(handle, cmd_buf); else if (handle->ae_algo->ops->dbg_run_cmd) ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); else @@ -833,6 +917,14 @@ static const struct hns3_dbg_func hns3_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_RX_BD, .dbg_dump_bd = hns3_dbg_rx_bd_info, }, + { + .cmd = HNAE3_DBG_CMD_RX_QUEUE_INFO, + .dbg_dump = hns3_dbg_rx_queue_info, + }, + { + .cmd = HNAE3_DBG_CMD_TX_QUEUE_INFO, + .dbg_dump = hns3_dbg_tx_queue_info, + }, };
static int hns3_dbg_read_cmd(struct hns3_dbg_data *dbg_data, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index 4cab37a5d44a..0e109b03f89e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -6,6 +6,7 @@
#define HNS3_DBG_READ_LEN 65536 #define HNS3_DBG_READ_LEN_128KB 0x20000 +#define HNS3_DBG_READ_LEN_1MB 0x100000 #define HNS3_DBG_READ_LEN_4MB 0x400000 #define HNS3_DBG_WRITE_LEN 1024
From: Hao Chen chenhao288@hisilicon.com
mainline inclusion from mainline-master commit b5a0b70d77b9be91b8e6dfa5dd3b39ea9cf6be4c category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for fd tcam is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "fd_tcam" for it, and query it by command "cat fd_tcam", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat fd_tcam read result tcam key x(31): 00000000 00000000 00000000 08000000 00000600 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 read result tcam key y(31): 00000000 00000000 00000000 f7ff0000 0000f900 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000fff8
Signed-off-by: Hao Chen chenhao288@hisilicon.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 11 ++- .../ethernet/hisilicon/hns3/hns3_debugfs.h | 1 + .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 88 ++++++++++++------- .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 5 ++ 5 files changed, 74 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index b7116015bcdd..c1b1065a0d7e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -278,6 +278,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_QUEUE_MAP, HNAE3_DBG_CMD_RX_QUEUE_INFO, HNAE3_DBG_CMD_TX_QUEUE_INFO, + HNAE3_DBG_CMD_FD_TCAM, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 93455c7ed59d..37aa891f8133 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -29,6 +29,9 @@ static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { { .name = "queue" }, + { + .name = "fd" + }, /* keep common at the bottom and add new directory above */ { .name = "common" @@ -236,6 +239,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN_1MB, .init = hns3_dbg_common_file_init, }, + { + .name = "fd_tcam", + .cmd = HNAE3_DBG_CMD_FD_TCAM, + .dentry = HNS3_DBG_DENTRY_FD, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -707,7 +717,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) if (!hns3_is_phys_func(h->pdev)) return;
- dev_info(&h->pdev->dev, "dump fd tcam\n"); dev_info(&h->pdev->dev, "dump tc\n"); dev_info(&h->pdev->dev, "dump tm map <q_num>\n"); dev_info(&h->pdev->dev, "dump tm\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h index 0e109b03f89e..f3766ff38bb7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h @@ -32,6 +32,7 @@ enum hns3_dbg_dentry_type { HNS3_DBG_DENTRY_MAC, HNS3_DBG_DENTRY_REG, HNS3_DBG_DENTRY_QUEUE, + HNS3_DBG_DENTRY_FD, HNS3_DBG_DENTRY_COMMON, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 1ad7bffb4d62..c92800d21cc1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1455,13 +1455,17 @@ static int hclge_dbg_dump_mng_table(struct hclge_dev *hdev, char *buf, int len) return 0; }
-static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage, - bool sel_x, u32 loc) +#define HCLGE_DBG_TCAM_BUF_SIZE 256 + +static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, bool sel_x, + char *tcam_buf, + struct hclge_dbg_tcam_msg tcam_msg) { struct hclge_fd_tcam_config_1_cmd *req1; struct hclge_fd_tcam_config_2_cmd *req2; struct hclge_fd_tcam_config_3_cmd *req3; struct hclge_desc desc[3]; + int pos = 0; int ret, i; u32 *req;
@@ -1475,31 +1479,35 @@ static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage, req2 = (struct hclge_fd_tcam_config_2_cmd *)desc[1].data; req3 = (struct hclge_fd_tcam_config_3_cmd *)desc[2].data;
- req1->stage = stage; + req1->stage = tcam_msg.stage; req1->xy_sel = sel_x ? 1 : 0; - req1->index = cpu_to_le32(loc); + req1->index = cpu_to_le32(tcam_msg.loc);
ret = hclge_cmd_send(&hdev->hw, desc, 3); if (ret) return ret;
- dev_info(&hdev->pdev->dev, " read result tcam key %s(%u):\n", - sel_x ? "x" : "y", loc); + pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos, + "read result tcam key %s(%u):\n", sel_x ? "x" : "y", + tcam_msg.loc);
/* tcam_data0 ~ tcam_data1 */ req = (u32 *)req1->tcam_data; for (i = 0; i < 2; i++) - dev_info(&hdev->pdev->dev, "%08x\n", *req++); + pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos, + "%08x\n", *req++);
/* tcam_data2 ~ tcam_data7 */ req = (u32 *)req2->tcam_data; for (i = 0; i < 6; i++) - dev_info(&hdev->pdev->dev, "%08x\n", *req++); + pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos, + "%08x\n", *req++);
/* tcam_data8 ~ tcam_data12 */ req = (u32 *)req3->tcam_data; for (i = 0; i < 5; i++) - dev_info(&hdev->pdev->dev, "%08x\n", *req++); + pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos, + "%08x\n", *req++);
return ret; } @@ -1517,59 +1525,75 @@ static int hclge_dbg_get_rules_location(struct hclge_dev *hdev, u16 *rule_locs) } spin_unlock_bh(&hdev->fd_rule_lock);
- if (cnt != hdev->hclge_fd_rule_num) + if (cnt != hdev->hclge_fd_rule_num || cnt == 0) return -EINVAL;
return cnt; }
-static void hclge_dbg_fd_tcam(struct hclge_dev *hdev) +static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len) { + u32 rule_num = hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]; + struct hclge_dbg_tcam_msg tcam_msg; int i, ret, rule_cnt; u16 *rule_locs; + char *tcam_buf; + int pos = 0;
if (!hnae3_dev_fd_supported(hdev)) { dev_err(&hdev->pdev->dev, "Only FD-supported dev supports dump fd tcam\n"); - return; + return -EOPNOTSUPP; }
- if (!hdev->hclge_fd_rule_num || - !hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]) - return; + if (!hdev->hclge_fd_rule_num || !rule_num) + return 0;
- rule_locs = kcalloc(hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1], - sizeof(u16), GFP_KERNEL); + rule_locs = kcalloc(rule_num, sizeof(u16), GFP_KERNEL); if (!rule_locs) - return; + return -ENOMEM; + + tcam_buf = kzalloc(HCLGE_DBG_TCAM_BUF_SIZE, GFP_KERNEL); + if (!tcam_buf) { + kfree(rule_locs); + return -ENOMEM; + }
rule_cnt = hclge_dbg_get_rules_location(hdev, rule_locs); - if (rule_cnt <= 0) { + if (rule_cnt < 0) { + ret = rule_cnt; dev_err(&hdev->pdev->dev, - "failed to get rule number, ret = %d\n", rule_cnt); - kfree(rule_locs); - return; + "failed to get rule number, ret = %d\n", ret); + goto out; }
for (i = 0; i < rule_cnt; i++) { - ret = hclge_dbg_fd_tcam_read(hdev, 0, true, rule_locs[i]); + tcam_msg.stage = HCLGE_FD_STAGE_1; + tcam_msg.loc = rule_locs[i]; + + ret = hclge_dbg_fd_tcam_read(hdev, true, tcam_buf, tcam_msg); if (ret) { dev_err(&hdev->pdev->dev, "failed to get fd tcam key x, ret = %d\n", ret); - kfree(rule_locs); - return; + goto out; }
- ret = hclge_dbg_fd_tcam_read(hdev, 0, false, rule_locs[i]); + pos += scnprintf(buf + pos, len - pos, "%s", tcam_buf); + + ret = hclge_dbg_fd_tcam_read(hdev, false, tcam_buf, tcam_msg); if (ret) { dev_err(&hdev->pdev->dev, "failed to get fd tcam key y, ret = %d\n", ret); - kfree(rule_locs); - return; + goto out; } + + pos += scnprintf(buf + pos, len - pos, "%s", tcam_buf); }
+out: + kfree(tcam_buf); kfree(rule_locs); + return ret; }
int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len) @@ -1994,9 +2018,7 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (strncmp(cmd_buf, "dump fd tcam", 12) == 0) { - hclge_dbg_fd_tcam(hdev); - } else if (strncmp(cmd_buf, "dump tc", 7) == 0) { + if (strncmp(cmd_buf, "dump tc", 7) == 0) { hclge_dbg_dump_tc(hdev); } else if (strncmp(cmd_buf, DUMP_TM_MAP, strlen(DUMP_TM_MAP)) == 0) { hclge_dbg_dump_tm_map(hdev, &cmd_buf[sizeof(DUMP_TM_MAP)]); @@ -2112,6 +2134,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_REG_DCB, .dbg_dump = hclge_dbg_dump_dcb, }, + { + .cmd = HNAE3_DBG_CMD_FD_TCAM, + .dbg_dump = hclge_dbg_dump_fd_tcam, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index 933f157294fd..25b42da471e5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -69,6 +69,11 @@ struct hclge_dbg_reg_common_msg { enum hclge_opcode_type cmd; };
+struct hclge_dbg_tcam_msg { + u8 stage; + u32 loc; +}; + #define HCLGE_DBG_MAX_DFX_MSG_LEN 60 struct hclge_dbg_dfx_message { int flag;
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit 7679f28e32a48461be4d4c30c14d7be06300cd5d category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for tm map is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "tm_map" for it, and query it by command "cat tm_map", return the result to userspace, rather than record in dmesg.
As user can't specify queue id in cat command, driver will return info of all queue id.
The display style is below: $ cat tm_map queue_id qset_id pri_id tc_id 0000 0000 00 00 INDEX | TM BP QSET MAPPING: 0000 | 00000000:00000000:00000000:00000000:00000000:00000000:00000000 0256 | 00000000:00000000:00000000:00000000:00000000:00000002:00000000 0512 | 00000000:00000000:00000000:00000004:00000000:00000000:00000000 0768 | 00000000:00000008:00000000:00000000:00000000:00000000:00000000
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 169 ++++++++---------- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 60 +++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 2 + 5 files changed, 145 insertions(+), 95 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c1b1065a0d7e..e68533d7fc4b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -253,6 +253,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_NODES, HNAE3_DBG_CMD_TM_PRI, HNAE3_DBG_CMD_TM_QSET, + HNAE3_DBG_CMD_TM_MAP, HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 37aa891f8133..39a24cc143f6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -64,6 +64,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "tm_map", + .cmd = HNAE3_DBG_CMD_TM_MAP, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN_1MB, + .init = hns3_dbg_common_file_init, + }, { .name = "dev_info", .cmd = HNAE3_DBG_CMD_DEV_INFO, @@ -718,7 +725,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) return;
dev_info(&h->pdev->dev, "dump tc\n"); - dev_info(&h->pdev->dev, "dump tm map <q_num>\n"); dev_info(&h->pdev->dev, "dump tm\n"); dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index c92800d21cc1..58ee389342ce 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -905,115 +905,96 @@ static void hclge_dbg_dump_tm(struct hclge_dev *hdev) cmd, ret); }
-static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, - const char *cmd_buf) +static int hclge_dbg_dump_tm_bp_qset_map(struct hclge_dev *hdev, u8 tc_id, + char *buf, int len) { - struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd; - struct hclge_nq_to_qs_link_cmd *nq_to_qs_map; u32 qset_mapping[HCLGE_BP_EXT_GRP_NUM]; - struct hclge_qs_to_pri_link_cmd *map; - struct hclge_tqp_tx_queue_tc_cmd *tc; - u16 group_id, queue_id, qset_id; - enum hclge_opcode_type cmd; - u8 grp_num, pri_id, tc_id; + struct hclge_bp_to_qs_map_cmd *map; struct hclge_desc desc; - u16 qs_id_l; - u16 qs_id_h; + int pos = 0; + u8 group_id; + u8 grp_num; + u16 i = 0; int ret; - u32 i; - - ret = kstrtou16(cmd_buf, 0, &queue_id); - queue_id = (ret != 0) ? 0 : queue_id; - - cmd = HCLGE_OPC_TM_NQ_TO_QS_LINK; - nq_to_qs_map = (struct hclge_nq_to_qs_link_cmd *)desc.data; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - nq_to_qs_map->nq_id = cpu_to_le16(queue_id); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_map_cmd_send; - qset_id = le16_to_cpu(nq_to_qs_map->qset_id); - - /* convert qset_id to the following format, drop the vld bit - * | qs_id_h | vld | qs_id_l | - * qset_id: | 15 ~ 11 | 10 | 9 ~ 0 | - * \ \ / / - * \ \ / / - * qset_id: | 15 | 14 ~ 10 | 9 ~ 0 | - */ - qs_id_l = hnae3_get_field(qset_id, HCLGE_TM_QS_ID_L_MSK, - HCLGE_TM_QS_ID_L_S); - qs_id_h = hnae3_get_field(qset_id, HCLGE_TM_QS_ID_H_EXT_MSK, - HCLGE_TM_QS_ID_H_EXT_S); - qset_id = 0; - hnae3_set_field(qset_id, HCLGE_TM_QS_ID_L_MSK, HCLGE_TM_QS_ID_L_S, - qs_id_l); - hnae3_set_field(qset_id, HCLGE_TM_QS_ID_H_MSK, HCLGE_TM_QS_ID_H_S, - qs_id_h); - - cmd = HCLGE_OPC_TM_QS_TO_PRI_LINK; - map = (struct hclge_qs_to_pri_link_cmd *)desc.data; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - map->qs_id = cpu_to_le16(qset_id); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_map_cmd_send; - pri_id = map->priority; - - cmd = HCLGE_OPC_TQP_TX_QUEUE_TC; - tc = (struct hclge_tqp_tx_queue_tc_cmd *)desc.data; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - tc->queue_id = cpu_to_le16(queue_id); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_map_cmd_send; - tc_id = tc->tc_id & 0x7; - - dev_info(&hdev->pdev->dev, "queue_id | qset_id | pri_id | tc_id\n"); - dev_info(&hdev->pdev->dev, "%04u | %04u | %02u | %02u\n", - queue_id, qset_id, pri_id, tc_id); - - if (!hnae3_dev_dcb_supported(hdev)) { - dev_info(&hdev->pdev->dev, - "Only DCB-supported dev supports tm mapping\n"); - return; - }
grp_num = hdev->num_tqps <= HCLGE_TQP_MAX_SIZE_DEV_V2 ? HCLGE_BP_GRP_NUM : HCLGE_BP_EXT_GRP_NUM; - cmd = HCLGE_OPC_TM_BP_TO_QSET_MAPPING; - bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data; + map = (struct hclge_bp_to_qs_map_cmd *)desc.data; for (group_id = 0; group_id < grp_num; group_id++) { - hclge_cmd_setup_basic_desc(&desc, cmd, true); - bp_to_qs_map_cmd->tc_id = tc_id; - bp_to_qs_map_cmd->qs_group_id = group_id; + hclge_cmd_setup_basic_desc(&desc, + HCLGE_OPC_TM_BP_TO_QSET_MAPPING, + true); + map->tc_id = tc_id; + map->qs_group_id = group_id; ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_map_cmd_send; + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get bp to qset map, ret = %d\n", + ret); + return ret; + }
- qset_mapping[group_id] = - le32_to_cpu(bp_to_qs_map_cmd->qs_bit_map); + qset_mapping[group_id] = le32_to_cpu(map->qs_bit_map); }
- dev_info(&hdev->pdev->dev, "index | tm bp qset maping:\n"); - - i = 0; + pos += scnprintf(buf + pos, len - pos, "INDEX | TM BP QSET MAPPING:\n"); for (group_id = 0; group_id < grp_num / 8; group_id++) { - dev_info(&hdev->pdev->dev, + pos += scnprintf(buf + pos, len - pos, "%04d | %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n", - group_id * 256, qset_mapping[(u32)(i + 7)], - qset_mapping[(u32)(i + 6)], qset_mapping[(u32)(i + 5)], - qset_mapping[(u32)(i + 4)], qset_mapping[(u32)(i + 3)], - qset_mapping[(u32)(i + 2)], qset_mapping[(u32)(i + 1)], + group_id * 256, qset_mapping[i + 7], + qset_mapping[i + 6], qset_mapping[i + 5], + qset_mapping[i + 4], qset_mapping[i + 3], + qset_mapping[i + 2], qset_mapping[i + 1], qset_mapping[i]); i += 8; }
- return; + return pos; +}
-err_tm_map_cmd_send: - dev_err(&hdev->pdev->dev, "dump tqp map fail(0x%x), ret = %d\n", - cmd, ret); +static int hclge_dbg_dump_tm_map(struct hclge_dev *hdev, char *buf, int len) +{ + u16 queue_id; + u16 qset_id; + u8 link_vld; + int pos = 0; + u8 pri_id; + u8 tc_id; + int ret; + + for (queue_id = 0; queue_id < hdev->num_tqps; queue_id++) { + ret = hclge_tm_get_q_to_qs_map(hdev, queue_id, &qset_id); + if (ret) + return ret; + + ret = hclge_tm_get_qset_map_pri(hdev, qset_id, &pri_id, + &link_vld); + if (ret) + return ret; + + ret = hclge_tm_get_q_to_tc(hdev, queue_id, &tc_id); + if (ret) + return ret; + + pos += scnprintf(buf + pos, len - pos, + "QUEUE_ID QSET_ID PRI_ID TC_ID\n"); + pos += scnprintf(buf + pos, len - pos, + "%04u %4u %3u %2u\n", + queue_id, qset_id, pri_id, tc_id); + + if (!hnae3_dev_dcb_supported(hdev)) + continue; + + ret = hclge_dbg_dump_tm_bp_qset_map(hdev, tc_id, buf + pos, + len - pos); + if (ret < 0) + return ret; + pos += ret; + + pos += scnprintf(buf + pos, len - pos, "\n"); + } + + return 0; }
static int hclge_dbg_dump_tm_nodes(struct hclge_dev *hdev, char *buf, int len) @@ -2013,15 +1994,11 @@ static int hclge_dbg_dump_mac_mc(struct hclge_dev *hdev, char *buf, int len)
int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { -#define DUMP_TM_MAP "dump tm map" - struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
if (strncmp(cmd_buf, "dump tc", 7) == 0) { hclge_dbg_dump_tc(hdev); - } else if (strncmp(cmd_buf, DUMP_TM_MAP, strlen(DUMP_TM_MAP)) == 0) { - hclge_dbg_dump_tm_map(hdev, &cmd_buf[sizeof(DUMP_TM_MAP)]); } else if (strncmp(cmd_buf, "dump tm", 7) == 0) { hclge_dbg_dump_tm(hdev); } else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) { @@ -2058,6 +2035,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_TM_QSET, .dbg_dump = hclge_dbg_dump_tm_qset, }, + { + .cmd = HNAE3_DBG_CMD_TM_MAP, + .dbg_dump = hclge_dbg_dump_tm_map, + }, { .cmd = HNAE3_DBG_CMD_MAC_UC, .dbg_dump = hclge_dbg_dump_mac_uc, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index ebb962bad451..bd99faf19d9d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1807,3 +1807,63 @@ int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id, para->rate = le32_to_cpu(shap_cfg_cmd->pri_rate); return 0; } + +int hclge_tm_get_q_to_qs_map(struct hclge_dev *hdev, u16 q_id, u16 *qset_id) +{ + struct hclge_nq_to_qs_link_cmd *map; + struct hclge_desc desc; + u16 qs_id_l; + u16 qs_id_h; + int ret; + + map = (struct hclge_nq_to_qs_link_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NQ_TO_QS_LINK, true); + map->nq_id = cpu_to_le16(q_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get queue to qset map, ret = %d\n", ret); + return ret; + } + *qset_id = le16_to_cpu(map->qset_id); + + /* convert qset_id to the following format, drop the vld bit + * | qs_id_h | vld | qs_id_l | + * qset_id: | 15 ~ 11 | 10 | 9 ~ 0 | + * \ \ / / + * \ \ / / + * qset_id: | 15 | 14 ~ 10 | 9 ~ 0 | + */ + qs_id_l = hnae3_get_field(*qset_id, HCLGE_TM_QS_ID_L_MSK, + HCLGE_TM_QS_ID_L_S); + qs_id_h = hnae3_get_field(*qset_id, HCLGE_TM_QS_ID_H_EXT_MSK, + HCLGE_TM_QS_ID_H_EXT_S); + *qset_id = 0; + hnae3_set_field(*qset_id, HCLGE_TM_QS_ID_L_MSK, HCLGE_TM_QS_ID_L_S, + qs_id_l); + hnae3_set_field(*qset_id, HCLGE_TM_QS_ID_H_MSK, HCLGE_TM_QS_ID_H_S, + qs_id_h); + return 0; +} + +int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id) +{ +#define HCLGE_TM_TC_MASK 0x7 + + struct hclge_tqp_tx_queue_tc_cmd *tc; + struct hclge_desc desc; + int ret; + + tc = (struct hclge_tqp_tx_queue_tc_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TQP_TX_QUEUE_TC, true); + tc->queue_id = cpu_to_le16(q_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get queue to tc map, ret = %d\n", ret); + return ret; + } + + *tc_id = tc->tc_id & HCLGE_TM_TC_MASK; + return 0; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index b25d76023af0..c21e822fefbf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -242,4 +242,6 @@ int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight); int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id, enum hclge_opcode_type cmd, struct hclge_pri_shaper_para *para); +int hclge_tm_get_q_to_qs_map(struct hclge_dev *hdev, u16 q_id, u16 *qset_id); +int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id); #endif
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit cad7c215a4b1bc67920ab0d2673ac08a2cc885f1 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, user gets some tm info by implementing debugfs command "echo dump tm > cmd", this command will dump info in dmesg. It's unnecessary and heavy.
In addition, the info of this command mixes info of qset, priority, pg and port. Qset and priority have their own command to get info of themself, so can remove info of qset and priority from this command.
To optimize it, create two new files "tm_pg", "tm_port" in tm directory and use cat command to separately get info of pg and port.
The display style is below: $ cat tm_pg ID PRI_MAP MODE DWRR C_IR_B C_IR_U C_IR_S C_BS_B C_BS_S ... 00 0x1f dwrr 1 75 9 0 31 20 ...
$ cat tm_port IR_B IR_U IR_S BS_B BS_S FLAG RATE(Mbps) 75 9 0 31 20 1 200000
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 15 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 304 ++++++------------ .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 2 + .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 125 ++++++- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 15 +- 6 files changed, 257 insertions(+), 206 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index e68533d7fc4b..567556d934a8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -254,6 +254,8 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_PRI, HNAE3_DBG_CMD_TM_QSET, HNAE3_DBG_CMD_TM_MAP, + HNAE3_DBG_CMD_TM_PG, + HNAE3_DBG_CMD_TM_PORT, HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 39a24cc143f6..4061f1f36739 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -71,6 +71,20 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN_1MB, .init = hns3_dbg_common_file_init, }, + { + .name = "tm_pg", + .cmd = HNAE3_DBG_CMD_TM_PG, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, + { + .name = "tm_port", + .cmd = HNAE3_DBG_CMD_TM_PORT, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, { .name = "dev_info", .cmd = HNAE3_DBG_CMD_DEV_INFO, @@ -725,7 +739,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) return;
dev_info(&h->pdev->dev, "dump tc\n"); - dev_info(&h->pdev->dev, "dump tm\n"); dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 58ee389342ce..506f0abfe46d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -685,224 +685,120 @@ static void hclge_dbg_dump_tc(struct hclge_dev *hdev) hclge_print_tc_info(hdev, ets_weight->tc_weight[i], i); }
-static void hclge_dbg_dump_tm_pg(struct hclge_dev *hdev) -{ - struct hclge_port_shapping_cmd *port_shap_cfg_cmd; - struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd; - struct hclge_pg_shapping_cmd *pg_shap_cfg_cmd; - enum hclge_opcode_type cmd; - struct hclge_desc desc; - int ret; +static const struct hclge_dbg_item tm_pg_items[] = { + { "ID", 2 }, + { "PRI_MAP", 2 }, + { "MODE", 2 }, + { "DWRR", 2 }, + { "C_IR_B", 2 }, + { "C_IR_U", 2 }, + { "C_IR_S", 2 }, + { "C_BS_B", 2 }, + { "C_BS_S", 2 }, + { "C_FLAG", 2 }, + { "C_RATE(Mbps)", 2 }, + { "P_IR_B", 2 }, + { "P_IR_U", 2 }, + { "P_IR_S", 2 }, + { "P_BS_B", 2 }, + { "P_BS_S", 2 }, + { "P_FLAG", 2 }, + { "P_RATE(Mbps)", 0 } +};
- cmd = HCLGE_OPC_TM_PG_C_SHAPPING; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; +static void hclge_dbg_fill_shaper_content(struct hclge_tm_shaper_para *para, + char **result, u8 *index) +{ + sprintf(result[(*index)++], "%3u", para->ir_b); + sprintf(result[(*index)++], "%3u", para->ir_u); + sprintf(result[(*index)++], "%3u", para->ir_s); + sprintf(result[(*index)++], "%3u", para->bs_b); + sprintf(result[(*index)++], "%3u", para->bs_s); + sprintf(result[(*index)++], "%3u", para->flag); + sprintf(result[(*index)++], "%6u", para->rate); +}
- pg_shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PG_C pg_id: %u\n", pg_shap_cfg_cmd->pg_id); - dev_info(&hdev->pdev->dev, "PG_C pg_shapping: 0x%x\n", - le32_to_cpu(pg_shap_cfg_cmd->pg_shapping_para)); +static int hclge_dbg_dump_tm_pg(struct hclge_dev *hdev, char *buf, int len) +{ + char data_str[ARRAY_SIZE(tm_pg_items)][HCLGE_DBG_DATA_STR_LEN]; + struct hclge_tm_shaper_para c_shaper_para, p_shaper_para; + char *result[ARRAY_SIZE(tm_pg_items)], *sch_mode_str; + u8 pg_id, sch_mode, weight, pri_bit_map, i, j; + char content[HCLGE_DBG_TM_INFO_LEN]; + int pos = 0; + int ret;
- cmd = HCLGE_OPC_TM_PG_P_SHAPPING; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; - - pg_shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PG_P pg_id: %u\n", pg_shap_cfg_cmd->pg_id); - dev_info(&hdev->pdev->dev, "PG_P pg_shapping: 0x%x\n", - le32_to_cpu(pg_shap_cfg_cmd->pg_shapping_para)); - dev_info(&hdev->pdev->dev, "PG_P flag: %#x\n", pg_shap_cfg_cmd->flag); - dev_info(&hdev->pdev->dev, "PG_P pg_rate: %u(Mbps)\n", - le32_to_cpu(pg_shap_cfg_cmd->pg_rate)); - - cmd = HCLGE_OPC_TM_PORT_SHAPPING; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; + for (i = 0; i < ARRAY_SIZE(tm_pg_items); i++) + result[i] = &data_str[i][0];
- port_shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PORT port_shapping: 0x%x\n", - le32_to_cpu(port_shap_cfg_cmd->port_shapping_para)); - dev_info(&hdev->pdev->dev, "PORT flag: %#x\n", port_shap_cfg_cmd->flag); - dev_info(&hdev->pdev->dev, "PORT port_rate: %u(Mbps)\n", - le32_to_cpu(port_shap_cfg_cmd->port_rate)); + hclge_dbg_fill_content(content, sizeof(content), tm_pg_items, + NULL, ARRAY_SIZE(tm_pg_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content);
- cmd = HCLGE_OPC_TM_PG_SCH_MODE_CFG; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; + for (pg_id = 0; pg_id < hdev->tm_info.num_pg; pg_id++) { + ret = hclge_tm_get_pg_to_pri_map(hdev, pg_id, &pri_bit_map); + if (ret) + return ret;
- dev_info(&hdev->pdev->dev, "PG_SCH pg_id: %u\n", - le32_to_cpu(desc.data[0])); + ret = hclge_tm_get_pg_sch_mode(hdev, pg_id, &sch_mode); + if (ret) + return ret;
- cmd = HCLGE_OPC_TM_PRI_SCH_MODE_CFG; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; + ret = hclge_tm_get_pg_weight(hdev, pg_id, &weight); + if (ret) + return ret;
- dev_info(&hdev->pdev->dev, "PRI_SCH pri_id: %u\n", - le32_to_cpu(desc.data[0])); + ret = hclge_tm_get_pg_shaper(hdev, pg_id, + HCLGE_OPC_TM_PG_C_SHAPPING, + &c_shaper_para); + if (ret) + return ret;
- cmd = HCLGE_OPC_TM_QS_SCH_MODE_CFG; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; + ret = hclge_tm_get_pg_shaper(hdev, pg_id, + HCLGE_OPC_TM_PG_P_SHAPPING, + &p_shaper_para); + if (ret) + return ret;
- dev_info(&hdev->pdev->dev, "QS_SCH qs_id: %u\n", - le32_to_cpu(desc.data[0])); + sch_mode_str = sch_mode & HCLGE_TM_TX_SCHD_DWRR_MSK ? "dwrr" : + "sp";
- if (!hnae3_dev_dcb_supported(hdev)) { - dev_info(&hdev->pdev->dev, - "Only DCB-supported dev supports tm mapping\n"); - return; + j = 0; + sprintf(result[j++], "%02u", pg_id); + sprintf(result[j++], "0x%02x", pri_bit_map); + sprintf(result[j++], "%4s", sch_mode_str); + sprintf(result[j++], "%3u", weight); + hclge_dbg_fill_shaper_content(&c_shaper_para, result, &j); + hclge_dbg_fill_shaper_content(&p_shaper_para, result, &j); + + hclge_dbg_fill_content(content, sizeof(content), tm_pg_items, + (const char **)result, + ARRAY_SIZE(tm_pg_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); }
- cmd = HCLGE_OPC_TM_BP_TO_QSET_MAPPING; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_pg_cmd_send; - - bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "BP_TO_QSET tc_id: %u\n", - bp_to_qs_map_cmd->tc_id); - dev_info(&hdev->pdev->dev, "BP_TO_QSET qs_group_id: 0x%x\n", - bp_to_qs_map_cmd->qs_group_id); - dev_info(&hdev->pdev->dev, "BP_TO_QSET qs_bit_map: 0x%x\n", - le32_to_cpu(bp_to_qs_map_cmd->qs_bit_map)); - return; - -err_tm_pg_cmd_send: - dev_err(&hdev->pdev->dev, "dump tm_pg fail(0x%x), ret = %d\n", - cmd, ret); + return 0; }
-static void hclge_dbg_dump_tm(struct hclge_dev *hdev) +static int hclge_dbg_dump_tm_port(struct hclge_dev *hdev, char *buf, int len) { - struct hclge_priority_weight_cmd *priority_weight; - struct hclge_pg_to_pri_link_cmd *pg_to_pri_map; - struct hclge_qs_to_pri_link_cmd *qs_to_pri_map; - struct hclge_nq_to_qs_link_cmd *nq_to_qs_map; - struct hclge_pri_shapping_cmd *shap_cfg_cmd; - struct hclge_pg_weight_cmd *pg_weight; - struct hclge_qs_weight_cmd *qs_weight; - enum hclge_opcode_type cmd; - struct hclge_desc desc; + struct hclge_tm_shaper_para shaper_para; + int pos = 0; int ret;
- cmd = HCLGE_OPC_TM_PG_TO_PRI_LINK; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - pg_to_pri_map = (struct hclge_pg_to_pri_link_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "dump tm\n"); - dev_info(&hdev->pdev->dev, "PG_TO_PRI gp_id: %u\n", - pg_to_pri_map->pg_id); - dev_info(&hdev->pdev->dev, "PG_TO_PRI map: 0x%x\n", - pg_to_pri_map->pri_bit_map); - - cmd = HCLGE_OPC_TM_QS_TO_PRI_LINK; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - qs_to_pri_map = (struct hclge_qs_to_pri_link_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "QS_TO_PRI qs_id: %u\n", - le16_to_cpu(qs_to_pri_map->qs_id)); - dev_info(&hdev->pdev->dev, "QS_TO_PRI priority: %u\n", - qs_to_pri_map->priority); - dev_info(&hdev->pdev->dev, "QS_TO_PRI link_vld: %u\n", - qs_to_pri_map->link_vld); - - cmd = HCLGE_OPC_TM_NQ_TO_QS_LINK; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - nq_to_qs_map = (struct hclge_nq_to_qs_link_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "NQ_TO_QS nq_id: %u\n", - le16_to_cpu(nq_to_qs_map->nq_id)); - dev_info(&hdev->pdev->dev, "NQ_TO_QS qset_id: 0x%x\n", - le16_to_cpu(nq_to_qs_map->qset_id)); - - cmd = HCLGE_OPC_TM_PG_WEIGHT; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - pg_weight = (struct hclge_pg_weight_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PG pg_id: %u\n", pg_weight->pg_id); - dev_info(&hdev->pdev->dev, "PG dwrr: %u\n", pg_weight->dwrr); - - cmd = HCLGE_OPC_TM_QS_WEIGHT; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - qs_weight = (struct hclge_qs_weight_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "QS qs_id: %u\n", - le16_to_cpu(qs_weight->qs_id)); - dev_info(&hdev->pdev->dev, "QS dwrr: %u\n", qs_weight->dwrr); - - cmd = HCLGE_OPC_TM_PRI_WEIGHT; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); + ret = hclge_tm_get_port_shaper(hdev, &shaper_para); if (ret) - goto err_tm_cmd_send; - - priority_weight = (struct hclge_priority_weight_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PRI pri_id: %u\n", priority_weight->pri_id); - dev_info(&hdev->pdev->dev, "PRI dwrr: %u\n", priority_weight->dwrr); - - cmd = HCLGE_OPC_TM_PRI_C_SHAPPING; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PRI_C pri_id: %u\n", shap_cfg_cmd->pri_id); - dev_info(&hdev->pdev->dev, "PRI_C pri_shapping: 0x%x\n", - le32_to_cpu(shap_cfg_cmd->pri_shapping_para)); - dev_info(&hdev->pdev->dev, "PRI_C flag: %#x\n", shap_cfg_cmd->flag); - dev_info(&hdev->pdev->dev, "PRI_C pri_rate: %u(Mbps)\n", - le32_to_cpu(shap_cfg_cmd->pri_rate)); - - cmd = HCLGE_OPC_TM_PRI_P_SHAPPING; - hclge_cmd_setup_basic_desc(&desc, cmd, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) - goto err_tm_cmd_send; - - shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "PRI_P pri_id: %u\n", shap_cfg_cmd->pri_id); - dev_info(&hdev->pdev->dev, "PRI_P pri_shapping: 0x%x\n", - le32_to_cpu(shap_cfg_cmd->pri_shapping_para)); - dev_info(&hdev->pdev->dev, "PRI_P flag: %#x\n", shap_cfg_cmd->flag); - dev_info(&hdev->pdev->dev, "PRI_P pri_rate: %u(Mbps)\n", - le32_to_cpu(shap_cfg_cmd->pri_rate)); - - hclge_dbg_dump_tm_pg(hdev); + return ret;
- return; + pos += scnprintf(buf + pos, len - pos, + "IR_B IR_U IR_S BS_B BS_S FLAG RATE(Mbps)\n"); + pos += scnprintf(buf + pos, len - pos, + "%3u %3u %3u %3u %3u %1u %6u\n", + shaper_para.ir_b, shaper_para.ir_u, shaper_para.ir_s, + shaper_para.bs_b, shaper_para.bs_s, shaper_para.flag, + shaper_para.rate);
-err_tm_cmd_send: - dev_err(&hdev->pdev->dev, "dump tm fail(0x%x), ret = %d\n", - cmd, ret); + return 0; }
static int hclge_dbg_dump_tm_bp_qset_map(struct hclge_dev *hdev, u8 tc_id, @@ -1031,8 +927,8 @@ static int hclge_dbg_dump_tm_nodes(struct hclge_dev *hdev, char *buf, int len)
static int hclge_dbg_dump_tm_pri(struct hclge_dev *hdev, char *buf, int len) { - struct hclge_pri_shaper_para c_shaper_para; - struct hclge_pri_shaper_para p_shaper_para; + struct hclge_tm_shaper_para c_shaper_para; + struct hclge_tm_shaper_para p_shaper_para; u8 pri_num, sch_mode, weight; char *sch_mode_str; int pos = 0; @@ -1999,8 +1895,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
if (strncmp(cmd_buf, "dump tc", 7) == 0) { hclge_dbg_dump_tc(hdev); - } else if (strncmp(cmd_buf, "dump tm", 7) == 0) { - hclge_dbg_dump_tm(hdev); } else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) { hclge_dbg_dump_qos_pause_cfg(hdev); } else if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) { @@ -2039,6 +1933,14 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_TM_MAP, .dbg_dump = hclge_dbg_dump_tm_map, }, + { + .cmd = HNAE3_DBG_CMD_TM_PG, + .dbg_dump = hclge_dbg_dump_tm_pg, + }, + { + .cmd = HNAE3_DBG_CMD_TM_PORT, + .dbg_dump = hclge_dbg_dump_tm_port, + }, { .cmd = HNAE3_DBG_CMD_MAC_UC, .dbg_dump = hclge_dbg_dump_mac_uc, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index 25b42da471e5..c4956e3d8a41 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -738,6 +738,8 @@ static const struct hclge_dbg_dfx_message hclge_dbg_tqp_reg[] = { #define HCLGE_DBG_ID_LEN 16 #define HCLGE_DBG_ITEM_NAME_LEN 32 #define HCLGE_DBG_DATA_STR_LEN 32 +#define HCLGE_DBG_TM_INFO_LEN 256 + struct hclge_dbg_item { char name[HCLGE_DBG_ITEM_NAME_LEN]; u16 interval; /* blank numbers after the item */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index bd99faf19d9d..45870fec0506 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1775,7 +1775,7 @@ int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight)
int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id, enum hclge_opcode_type cmd, - struct hclge_pri_shaper_para *para) + struct hclge_tm_shaper_para *para) { struct hclge_pri_shapping_cmd *shap_cfg_cmd; struct hclge_desc desc; @@ -1867,3 +1867,126 @@ int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id) *tc_id = tc->tc_id & HCLGE_TM_TC_MASK; return 0; } + +int hclge_tm_get_pg_to_pri_map(struct hclge_dev *hdev, u8 pg_id, + u8 *pri_bit_map) +{ + struct hclge_pg_to_pri_link_cmd *map; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_TO_PRI_LINK, true); + map = (struct hclge_pg_to_pri_link_cmd *)desc.data; + map->pg_id = pg_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get pg to pri map, ret = %d\n", ret); + return ret; + } + + *pri_bit_map = map->pri_bit_map; + return 0; +} + +int hclge_tm_get_pg_weight(struct hclge_dev *hdev, u8 pg_id, u8 *weight) +{ + struct hclge_pg_weight_cmd *pg_weight_cmd; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_WEIGHT, true); + pg_weight_cmd = (struct hclge_pg_weight_cmd *)desc.data; + pg_weight_cmd->pg_id = pg_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get pg weight, ret = %d\n", ret); + return ret; + } + + *weight = pg_weight_cmd->dwrr; + return 0; +} + +int hclge_tm_get_pg_sch_mode(struct hclge_dev *hdev, u8 pg_id, u8 *mode) +{ + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, true); + desc.data[0] = cpu_to_le32(pg_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get pg sch mode, ret = %d\n", ret); + return ret; + } + + *mode = (u8)le32_to_cpu(desc.data[1]); + return 0; +} + +int hclge_tm_get_pg_shaper(struct hclge_dev *hdev, u8 pg_id, + enum hclge_opcode_type cmd, + struct hclge_tm_shaper_para *para) +{ + struct hclge_pg_shapping_cmd *shap_cfg_cmd; + struct hclge_desc desc; + u32 shapping_para; + int ret; + + if (cmd != HCLGE_OPC_TM_PG_C_SHAPPING && + cmd != HCLGE_OPC_TM_PG_P_SHAPPING) + return -EINVAL; + + hclge_cmd_setup_basic_desc(&desc, cmd, true); + shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data; + shap_cfg_cmd->pg_id = pg_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get pg shaper(%#x), ret = %d\n", + cmd, ret); + return ret; + } + + shapping_para = le32_to_cpu(shap_cfg_cmd->pg_shapping_para); + para->ir_b = hclge_tm_get_field(shapping_para, IR_B); + para->ir_u = hclge_tm_get_field(shapping_para, IR_U); + para->ir_s = hclge_tm_get_field(shapping_para, IR_S); + para->bs_b = hclge_tm_get_field(shapping_para, BS_B); + para->bs_s = hclge_tm_get_field(shapping_para, BS_S); + para->flag = shap_cfg_cmd->flag; + para->rate = le32_to_cpu(shap_cfg_cmd->pg_rate); + return 0; +} + +int hclge_tm_get_port_shaper(struct hclge_dev *hdev, + struct hclge_tm_shaper_para *para) +{ + struct hclge_port_shapping_cmd *port_shap_cfg_cmd; + struct hclge_desc desc; + u32 shapping_para; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PORT_SHAPPING, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get port shaper, ret = %d\n", ret); + return ret; + } + + port_shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data; + shapping_para = le32_to_cpu(port_shap_cfg_cmd->port_shapping_para); + para->ir_b = hclge_tm_get_field(shapping_para, IR_B); + para->ir_u = hclge_tm_get_field(shapping_para, IR_U); + para->ir_s = hclge_tm_get_field(shapping_para, IR_S); + para->bs_b = hclge_tm_get_field(shapping_para, BS_B); + para->bs_s = hclge_tm_get_field(shapping_para, BS_S); + para->flag = port_shap_cfg_cmd->flag; + para->rate = le32_to_cpu(port_shap_cfg_cmd->port_rate); + + return 0; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index c21e822fefbf..d6f148171353 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -199,14 +199,14 @@ struct hclge_tm_nodes_cmd { __le16 queue_num; };
-struct hclge_pri_shaper_para { +struct hclge_tm_shaper_para { + u32 rate; u8 ir_b; u8 ir_u; u8 ir_s; u8 bs_b; u8 bs_s; u8 flag; - u32 rate; };
#define hclge_tm_set_field(dest, string, val) \ @@ -241,7 +241,16 @@ int hclge_tm_get_pri_sch_mode(struct hclge_dev *hdev, u8 pri_id, u8 *mode); int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight); int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id, enum hclge_opcode_type cmd, - struct hclge_pri_shaper_para *para); + struct hclge_tm_shaper_para *para); int hclge_tm_get_q_to_qs_map(struct hclge_dev *hdev, u16 q_id, u16 *qset_id); int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id); +int hclge_tm_get_pg_to_pri_map(struct hclge_dev *hdev, u8 pg_id, + u8 *pri_bit_map); +int hclge_tm_get_pg_weight(struct hclge_dev *hdev, u8 pg_id, u8 *weight); +int hclge_tm_get_pg_sch_mode(struct hclge_dev *hdev, u8 pg_id, u8 *mode); +int hclge_tm_get_pg_shaper(struct hclge_dev *hdev, u8 pg_id, + enum hclge_opcode_type cmd, + struct hclge_tm_shaper_para *para); +int hclge_tm_get_port_shaper(struct hclge_dev *hdev, + struct hclge_tm_shaper_para *para); #endif
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit 0e32038dc8565e8f1c00129307d56fd336267a56 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, user gets tc schedule info by implementing debugfs command "echo dump tc > cmd", this command will dump info in dmesg. It's unnecessary and heavy.
To optimize it, create a single file "tc_sch_info" and use cat command to get info. It will return info to userspace, rather than record in dmesg.
The display style is below: $ cat tc_sch_info enabled tc number: 4 weight_offset: 14 TC MODE WEIGHT 0 dwrr 25 1 dwrr 25 2 dwrr 25 3 dwrr 25 4 dwrr 0 5 dwrr 0 6 dwrr 0 7 dwrr 0
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 ++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 55 ++++++++++--------- 3 files changed, 37 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 567556d934a8..5874e8449aaf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -256,6 +256,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_MAP, HNAE3_DBG_CMD_TM_PG, HNAE3_DBG_CMD_TM_PORT, + HNAE3_DBG_CMD_TC_SCH_INFO, HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 4061f1f36739..1719ff8b3a20 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -85,6 +85,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "tc_sch_info", + .cmd = HNAE3_DBG_CMD_TC_SCH_INFO, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, { .name = "dev_info", .cmd = HNAE3_DBG_CMD_DEV_INFO, @@ -738,7 +745,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) if (!hns3_is_phys_func(h->pdev)) return;
- dev_info(&h->pdev->dev, "dump tc\n"); dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 506f0abfe46d..bd62103d4aa8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -645,44 +645,45 @@ static int hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, return ret; }
-static void hclge_print_tc_info(struct hclge_dev *hdev, bool flag, int index) -{ - if (flag) - dev_info(&hdev->pdev->dev, "tc(%d): no sp mode weight: %u\n", - index, hdev->tm_info.pg_info[0].tc_dwrr[index]); - else - dev_info(&hdev->pdev->dev, "tc(%d): sp mode\n", index); -} - -static void hclge_dbg_dump_tc(struct hclge_dev *hdev) +static int hclge_dbg_dump_tc(struct hclge_dev *hdev, char *buf, int len) { struct hclge_ets_tc_weight_cmd *ets_weight; struct hclge_desc desc; - int i, ret; + char *sch_mode_str; + int pos = 0; + int ret; + u8 i;
if (!hnae3_dev_dcb_supported(hdev)) { - dev_info(&hdev->pdev->dev, - "Only DCB-supported dev supports tc\n"); - return; + dev_err(&hdev->pdev->dev, + "Only DCB-supported dev supports tc\n"); + return -EOPNOTSUPP; }
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { - dev_err(&hdev->pdev->dev, "dump tc fail, ret = %d\n", ret); - return; + dev_err(&hdev->pdev->dev, "failed to get tc weight, ret = %d\n", + ret); + return ret; }
ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data;
- dev_info(&hdev->pdev->dev, "dump tc: %u tc enabled\n", - hdev->tm_info.num_tc); - dev_info(&hdev->pdev->dev, "weight_offset: %u\n", - ets_weight->weight_offset); + pos += scnprintf(buf + pos, len - pos, "enabled tc number: %u\n", + hdev->tm_info.num_tc); + pos += scnprintf(buf + pos, len - pos, "weight_offset: %u\n", + ets_weight->weight_offset); + + pos += scnprintf(buf + pos, len - pos, "TC MODE WEIGHT\n"); + for (i = 0; i < HNAE3_MAX_TC; i++) { + sch_mode_str = ets_weight->tc_weight[i] ? "dwrr" : "sp"; + pos += scnprintf(buf + pos, len - pos, "%u %4s %3u\n", + i, sch_mode_str, + hdev->tm_info.pg_info[0].tc_dwrr[i]); + }
- for (i = 0; i < HNAE3_MAX_TC; i++) - hclge_print_tc_info(hdev, ets_weight->tc_weight[i], i); + return 0; }
static const struct hclge_dbg_item tm_pg_items[] = { @@ -1893,9 +1894,7 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (strncmp(cmd_buf, "dump tc", 7) == 0) { - hclge_dbg_dump_tc(hdev); - } else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) { + if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) { hclge_dbg_dump_qos_pause_cfg(hdev); } else if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) { hclge_dbg_dump_qos_pri_map(hdev); @@ -1941,6 +1940,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_TM_PORT, .dbg_dump = hclge_dbg_dump_tm_port, }, + { + .cmd = HNAE3_DBG_CMD_TC_SCH_INFO, + .dbg_dump = hclge_dbg_dump_tc, + }, { .cmd = HNAE3_DBG_CMD_MAC_UC, .dbg_dump = hclge_dbg_dump_mac_uc,
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit 6571ec2eda65d4e19244bb3e001ec64a6eef41dc category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, user gets pause config by implementing debugfs command "echo dump qos pause cfg > cmd", this command will dump info in dmesg. It's unnecessary and heavy.
To optimize it, create a single file "qos_pause_cfg" in tm directory and use cat command to get info. It will return info to userspace, rather than record in dmesg.
The display style is below: $ cat qos_pause_cfg pause_trans_gap: 0x7f pause_trans_time: 0xffff
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 ++++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 30 +++++++++++-------- 3 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 5874e8449aaf..32f67eb4659b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -257,6 +257,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_PG, HNAE3_DBG_CMD_TM_PORT, HNAE3_DBG_CMD_TC_SCH_INFO, + HNAE3_DBG_CMD_QOS_PAUSE_CFG, HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 1719ff8b3a20..be2cde9ca052 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -92,6 +92,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "qos_pause_cfg", + .cmd = HNAE3_DBG_CMD_QOS_PAUSE_CFG, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, { .name = "dev_info", .cmd = HNAE3_DBG_CMD_DEV_INFO, @@ -745,7 +752,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) if (!hns3_is_phys_func(h->pdev)) return;
- dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index bd62103d4aa8..f7864f867eb6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1028,27 +1028,29 @@ static int hclge_dbg_dump_tm_qset(struct hclge_dev *hdev, char *buf, int len) return 0; }
-static void hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev, char *buf, + int len) { struct hclge_cfg_pause_param_cmd *pause_param; struct hclge_desc desc; + int pos = 0; int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { - dev_err(&hdev->pdev->dev, "dump checksum fail, ret = %d\n", - ret); - return; + dev_err(&hdev->pdev->dev, + "failed to dump qos pause, ret = %d\n", ret); + return ret; }
pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "dump qos pause cfg\n"); - dev_info(&hdev->pdev->dev, "pause_trans_gap: 0x%x\n", - pause_param->pause_trans_gap); - dev_info(&hdev->pdev->dev, "pause_trans_time: 0x%x\n", - le16_to_cpu(pause_param->pause_trans_time)); + + pos += scnprintf(buf + pos, len - pos, "pause_trans_gap: 0x%x\n", + pause_param->pause_trans_gap); + pos += scnprintf(buf + pos, len - pos, "pause_trans_time: 0x%x\n", + le16_to_cpu(pause_param->pause_trans_time)); + return 0; }
static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev) @@ -1894,9 +1896,7 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) { - hclge_dbg_dump_qos_pause_cfg(hdev); - } else if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) { + if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) { hclge_dbg_dump_qos_pri_map(hdev); } else if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { hclge_dbg_dump_qos_buf_cfg(hdev); @@ -1944,6 +1944,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_TC_SCH_INFO, .dbg_dump = hclge_dbg_dump_tc, }, + { + .cmd = HNAE3_DBG_CMD_QOS_PAUSE_CFG, + .dbg_dump = hclge_dbg_dump_qos_pause_cfg, + }, { .cmd = HNAE3_DBG_CMD_MAC_UC, .dbg_dump = hclge_dbg_dump_mac_uc,
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit 28d3bada7d42e324ee8558e6d22c3d768a87af7b category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, user gets priority map by implementing debugfs command "echo dump qos pri map > cmd", this command will dump info in dmesg. It's unnecessary and heavy.
To optimize it, create a single file "qos_pri_map" in tm directory and use cat command to get info. It will return info to userspace, rather than record in dmesg.
The display style is below: $ cat qos_pri_map vlan_to_pri: 0 PRI TC 0 0 1 1 2 2 3 3 4 0 5 1 6 2
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 45 ++++++++++++------- 3 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 32f67eb4659b..c99ad1481916 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -258,6 +258,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TM_PORT, HNAE3_DBG_CMD_TC_SCH_INFO, HNAE3_DBG_CMD_QOS_PAUSE_CFG, + HNAE3_DBG_CMD_QOS_PRI_MAP, HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index be2cde9ca052..e59060b5daad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -99,6 +99,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "qos_pri_map", + .cmd = HNAE3_DBG_CMD_QOS_PRI_MAP, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, { .name = "dev_info", .cmd = HNAE3_DBG_CMD_DEV_INFO, @@ -752,7 +759,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) if (!hns3_is_phys_func(h->pdev)) return;
- dev_info(&h->pdev->dev, "dump qos pri map\n"); dev_info(&h->pdev->dev, "dump qos buf cfg\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index f7864f867eb6..85129a5fef73 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1053,32 +1053,41 @@ static int hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev, char *buf, return 0; }
-static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev) +static int hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev, char *buf, + int len) { +#define HCLGE_DBG_TC_MASK 0x0F +#define HCLGE_DBG_TC_BIT_WIDTH 4 + struct hclge_qos_pri_map_cmd *pri_map; struct hclge_desc desc; + int pos = 0; + u8 *pri_tc; + u8 tc, i; int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "dump qos pri map fail, ret = %d\n", ret); - return; + "failed to dump qos pri map, ret = %d\n", ret); + return ret; }
pri_map = (struct hclge_qos_pri_map_cmd *)desc.data; - dev_info(&hdev->pdev->dev, "dump qos pri map\n"); - dev_info(&hdev->pdev->dev, "vlan_to_pri: 0x%x\n", pri_map->vlan_pri); - dev_info(&hdev->pdev->dev, "pri_0_to_tc: 0x%x\n", pri_map->pri0_tc); - dev_info(&hdev->pdev->dev, "pri_1_to_tc: 0x%x\n", pri_map->pri1_tc); - dev_info(&hdev->pdev->dev, "pri_2_to_tc: 0x%x\n", pri_map->pri2_tc); - dev_info(&hdev->pdev->dev, "pri_3_to_tc: 0x%x\n", pri_map->pri3_tc); - dev_info(&hdev->pdev->dev, "pri_4_to_tc: 0x%x\n", pri_map->pri4_tc); - dev_info(&hdev->pdev->dev, "pri_5_to_tc: 0x%x\n", pri_map->pri5_tc); - dev_info(&hdev->pdev->dev, "pri_6_to_tc: 0x%x\n", pri_map->pri6_tc); - dev_info(&hdev->pdev->dev, "pri_7_to_tc: 0x%x\n", pri_map->pri7_tc); + + pos += scnprintf(buf + pos, len - pos, "vlan_to_pri: 0x%x\n", + pri_map->vlan_pri); + pos += scnprintf(buf + pos, len - pos, "PRI TC\n"); + + pri_tc = (u8 *)pri_map; + for (i = 0; i < HNAE3_MAX_TC; i++) { + tc = pri_tc[i >> 1] >> ((i & 1) * HCLGE_DBG_TC_BIT_WIDTH); + tc &= HCLGE_DBG_TC_MASK; + pos += scnprintf(buf + pos, len - pos, "%u %u\n", i, tc); + } + + return 0; }
static int hclge_dbg_dump_tx_buf_cfg(struct hclge_dev *hdev) @@ -1896,9 +1905,7 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (strncmp(cmd_buf, "dump qos pri map", 16) == 0) { - hclge_dbg_dump_qos_pri_map(hdev); - } else if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { + if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { hclge_dbg_dump_qos_buf_cfg(hdev); } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); @@ -1948,6 +1955,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_QOS_PAUSE_CFG, .dbg_dump = hclge_dbg_dump_qos_pause_cfg, }, + { + .cmd = HNAE3_DBG_CMD_QOS_PRI_MAP, + .dbg_dump = hclge_dbg_dump_qos_pri_map, + }, { .cmd = HNAE3_DBG_CMD_MAC_UC, .dbg_dump = hclge_dbg_dump_mac_uc,
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit 95b195869b7d1eb7a1f837f024db31cd6fc07981 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, user gets qos buffer config by implementing debugfs command "echo dump qos buf cfg > cmd", this command will dump info in dmesg. It's unnecessary and heavy.
To optimize it, create a single file "qos_buf_cfg" in tm directory and use cat command to get info. It will return info to userspace, rather than record in dmesg.
The display style is below: $ cat qos_buf_cfg tx_packet_buf_tc_0: 0x120 tx_packet_buf_tc_1: 0x120 tx_packet_buf_tc_2: 0x120 tx_packet_buf_tc_3: 0x120 tx_packet_buf_tc_4: 0x0 tx_packet_buf_tc_5: 0x0 tx_packet_buf_tc_6: 0x0 tx_packet_buf_tc_7: 0x0 ......
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 186 ++++++++++-------- 3 files changed, 115 insertions(+), 80 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c99ad1481916..1fd35e1a1976 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -259,6 +259,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TC_SCH_INFO, HNAE3_DBG_CMD_QOS_PAUSE_CFG, HNAE3_DBG_CMD_QOS_PRI_MAP, + HNAE3_DBG_CMD_QOS_BUF_CFG, HNAE3_DBG_CMD_DEV_INFO, HNAE3_DBG_CMD_TX_BD, HNAE3_DBG_CMD_RX_BD, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index e59060b5daad..bd348c1c801b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -106,6 +106,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "qos_buf_cfg", + .cmd = HNAE3_DBG_CMD_QOS_BUF_CFG, + .dentry = HNS3_DBG_DENTRY_TM, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, { .name = "dev_info", .cmd = HNAE3_DBG_CMD_DEV_INFO, @@ -759,7 +766,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) if (!hns3_is_phys_func(h->pdev)) return;
- dev_info(&h->pdev->dev, "dump qos buf cfg\n"); dev_info(&h->pdev->dev, "dump mac tnl status\n"); dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 85129a5fef73..45ccb04100c5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1090,199 +1090,225 @@ static int hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev, char *buf, return 0; }
-static int hclge_dbg_dump_tx_buf_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_tx_buf_cfg(struct hclge_dev *hdev, char *buf, int len) { struct hclge_tx_buff_alloc_cmd *tx_buf_cmd; struct hclge_desc desc; + int pos = 0; int i, ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump tx buf, ret = %d\n", ret); return ret; + }
- dev_info(&hdev->pdev->dev, "dump qos buf cfg\n"); tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc.data; for (i = 0; i < HCLGE_MAX_TC_NUM; i++) - dev_info(&hdev->pdev->dev, "tx_packet_buf_tc_%d: 0x%x\n", i, - le16_to_cpu(tx_buf_cmd->tx_pkt_buff[i])); + pos += scnprintf(buf + pos, len - pos, + "tx_packet_buf_tc_%d: 0x%x\n", i, + le16_to_cpu(tx_buf_cmd->tx_pkt_buff[i]));
- return 0; + return pos; }
-static int hclge_dbg_dump_rx_priv_buf_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_rx_priv_buf_cfg(struct hclge_dev *hdev, char *buf, + int len) { struct hclge_rx_priv_buff_cmd *rx_buf_cmd; struct hclge_desc desc; + int pos = 0; int i, ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_PRIV_BUFF_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump rx priv buf, ret = %d\n", ret); return ret; + } + + pos += scnprintf(buf + pos, len - pos, "\n");
- dev_info(&hdev->pdev->dev, "\n"); rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc.data; for (i = 0; i < HCLGE_MAX_TC_NUM; i++) - dev_info(&hdev->pdev->dev, "rx_packet_buf_tc_%d: 0x%x\n", i, - le16_to_cpu(rx_buf_cmd->buf_num[i])); + pos += scnprintf(buf + pos, len - pos, + "rx_packet_buf_tc_%d: 0x%x\n", i, + le16_to_cpu(rx_buf_cmd->buf_num[i]));
- dev_info(&hdev->pdev->dev, "rx_share_buf: 0x%x\n", - le16_to_cpu(rx_buf_cmd->shared_buf)); + pos += scnprintf(buf + pos, len - pos, "rx_share_buf: 0x%x\n", + le16_to_cpu(rx_buf_cmd->shared_buf));
- return 0; + return pos; }
-static int hclge_dbg_dump_rx_common_wl_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_rx_common_wl_cfg(struct hclge_dev *hdev, char *buf, + int len) { struct hclge_rx_com_wl *rx_com_wl; struct hclge_desc desc; + int pos = 0; int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_COM_WL_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump rx common wl, ret = %d\n", ret); return ret; + }
rx_com_wl = (struct hclge_rx_com_wl *)desc.data; - dev_info(&hdev->pdev->dev, "\n"); - dev_info(&hdev->pdev->dev, "rx_com_wl: high: 0x%x, low: 0x%x\n", - le16_to_cpu(rx_com_wl->com_wl.high), - le16_to_cpu(rx_com_wl->com_wl.low)); + pos += scnprintf(buf + pos, len - pos, "\n"); + pos += scnprintf(buf + pos, len - pos, + "rx_com_wl: high: 0x%x, low: 0x%x\n", + le16_to_cpu(rx_com_wl->com_wl.high), + le16_to_cpu(rx_com_wl->com_wl.low));
- return 0; + return pos; }
-static int hclge_dbg_dump_rx_global_pkt_cnt(struct hclge_dev *hdev) +static int hclge_dbg_dump_rx_global_pkt_cnt(struct hclge_dev *hdev, char *buf, + int len) { struct hclge_rx_com_wl *rx_packet_cnt; struct hclge_desc desc; + int pos = 0; int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_GBL_PKT_CNT, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump rx global pkt cnt, ret = %d\n", ret); return ret; + }
rx_packet_cnt = (struct hclge_rx_com_wl *)desc.data; - dev_info(&hdev->pdev->dev, - "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n", - le16_to_cpu(rx_packet_cnt->com_wl.high), - le16_to_cpu(rx_packet_cnt->com_wl.low)); + pos += scnprintf(buf + pos, len - pos, + "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n", + le16_to_cpu(rx_packet_cnt->com_wl.high), + le16_to_cpu(rx_packet_cnt->com_wl.low));
- return 0; + return pos; }
-static int hclge_dbg_dump_rx_priv_wl_buf_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_rx_priv_wl_buf_cfg(struct hclge_dev *hdev, char *buf, + int len) { struct hclge_rx_priv_wl_buf *rx_priv_wl; struct hclge_desc desc[2]; + int pos = 0; int i, ret;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_RX_PRIV_WL_ALLOC, true); desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_RX_PRIV_WL_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, desc, 2); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump rx priv wl buf, ret = %d\n", ret); return ret; + }
rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[0].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) - dev_info(&hdev->pdev->dev, + pos += scnprintf(buf + pos, len - pos, "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i, le16_to_cpu(rx_priv_wl->tc_wl[i].high), le16_to_cpu(rx_priv_wl->tc_wl[i].low));
rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[1].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) - dev_info(&hdev->pdev->dev, + pos += scnprintf(buf + pos, len - pos, "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i + HCLGE_TC_NUM_ONE_DESC, le16_to_cpu(rx_priv_wl->tc_wl[i].high), le16_to_cpu(rx_priv_wl->tc_wl[i].low));
- return 0; + return pos; }
-static int hclge_dbg_dump_rx_common_threshold_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_rx_common_threshold_cfg(struct hclge_dev *hdev, + char *buf, int len) { struct hclge_rx_com_thrd *rx_com_thrd; struct hclge_desc desc[2]; + int pos = 0; int i, ret;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_RX_COM_THRD_ALLOC, true); desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_RX_COM_THRD_ALLOC, true); ret = hclge_cmd_send(&hdev->hw, desc, 2); - if (ret) + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to dump rx common threshold, ret = %d\n", ret); return ret; + }
- dev_info(&hdev->pdev->dev, "\n"); + pos += scnprintf(buf + pos, len - pos, "\n"); rx_com_thrd = (struct hclge_rx_com_thrd *)desc[0].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) - dev_info(&hdev->pdev->dev, + pos += scnprintf(buf + pos, len - pos, "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i, le16_to_cpu(rx_com_thrd->com_thrd[i].high), le16_to_cpu(rx_com_thrd->com_thrd[i].low));
rx_com_thrd = (struct hclge_rx_com_thrd *)desc[1].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) - dev_info(&hdev->pdev->dev, + pos += scnprintf(buf + pos, len - pos, "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i + HCLGE_TC_NUM_ONE_DESC, le16_to_cpu(rx_com_thrd->com_thrd[i].high), le16_to_cpu(rx_com_thrd->com_thrd[i].low));
- return 0; + return pos; }
-static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) +static int hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev, char *buf, + int len) { - enum hclge_opcode_type cmd; + int pos = 0; int ret;
- cmd = HCLGE_OPC_TX_BUFF_ALLOC; - ret = hclge_dbg_dump_tx_buf_cfg(hdev); - if (ret) - goto err_qos_cmd_send; - - cmd = HCLGE_OPC_RX_PRIV_BUFF_ALLOC; - ret = hclge_dbg_dump_rx_priv_buf_cfg(hdev); - if (ret) - goto err_qos_cmd_send; + ret = hclge_dbg_dump_tx_buf_cfg(hdev, buf + pos, len - pos); + if (ret < 0) + return ret; + pos += ret;
- cmd = HCLGE_OPC_RX_COM_WL_ALLOC; - ret = hclge_dbg_dump_rx_common_wl_cfg(hdev); - if (ret) - goto err_qos_cmd_send; + ret = hclge_dbg_dump_rx_priv_buf_cfg(hdev, buf + pos, len - pos); + if (ret < 0) + return ret; + pos += ret;
- cmd = HCLGE_OPC_RX_GBL_PKT_CNT; - ret = hclge_dbg_dump_rx_global_pkt_cnt(hdev); - if (ret) - goto err_qos_cmd_send; + ret = hclge_dbg_dump_rx_common_wl_cfg(hdev, buf + pos, len - pos); + if (ret < 0) + return ret; + pos += ret;
- dev_info(&hdev->pdev->dev, "\n"); - if (!hnae3_dev_dcb_supported(hdev)) { - dev_info(&hdev->pdev->dev, - "Only DCB-supported dev supports rx priv wl\n"); - return; - } + ret = hclge_dbg_dump_rx_global_pkt_cnt(hdev, buf + pos, len - pos); + if (ret < 0) + return ret; + pos += ret;
- cmd = HCLGE_OPC_RX_PRIV_WL_ALLOC; - ret = hclge_dbg_dump_rx_priv_wl_buf_cfg(hdev); - if (ret) - goto err_qos_cmd_send; + pos += scnprintf(buf + pos, len - pos, "\n"); + if (!hnae3_dev_dcb_supported(hdev)) + return 0;
- cmd = HCLGE_OPC_RX_COM_THRD_ALLOC; - ret = hclge_dbg_dump_rx_common_threshold_cfg(hdev); - if (ret) - goto err_qos_cmd_send; + ret = hclge_dbg_dump_rx_priv_wl_buf_cfg(hdev, buf + pos, len - pos); + if (ret < 0) + return ret; + pos += ret;
- return; + ret = hclge_dbg_dump_rx_common_threshold_cfg(hdev, buf + pos, + len - pos); + if (ret < 0) + return ret;
-err_qos_cmd_send: - dev_err(&hdev->pdev->dev, - "dump qos buf cfg fail(0x%x), ret = %d\n", cmd, ret); + return 0; }
static int hclge_dbg_dump_mng_table(struct hclge_dev *hdev, char *buf, int len) @@ -1905,9 +1931,7 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (strncmp(cmd_buf, "dump qos buf cfg", 16) == 0) { - hclge_dbg_dump_qos_buf_cfg(hdev); - } else if (strncmp(cmd_buf, "dump serv info", 14) == 0) { + if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { hclge_dbg_dump_mac_tnl_status(hdev); @@ -1959,6 +1983,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_QOS_PRI_MAP, .dbg_dump = hclge_dbg_dump_qos_pri_map, }, + { + .cmd = HNAE3_DBG_CMD_QOS_BUF_CFG, + .dbg_dump = hclge_dbg_dump_qos_buf_cfg, + }, { .cmd = HNAE3_DBG_CMD_MAC_UC, .dbg_dump = hclge_dbg_dump_mac_uc,
From: Guangbin Huang huangguangbin2@huawei.com
mainline inclusion from mainline-master commit 484e1ed1b25a6cd02ab25c871e670760f4b627b6 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, user gets qset shaper parameters by implementing debugfs command "echo dump qs shaper > cmd", this command will dump info in dmesg. It's unnecessary and heavy.
As there is "tm_qset" file in tm directory for dump qset info, to optimize these command, merge qset shaper parameters to tm_qset file and use cat command to get them.
The display style is below: $ cat tm_qset ID MAP_PRI LINK_VLD MODE DWRR IR_B IR_U IR_S BS_B BS_S FLAG 0000 0 1 dwrr 100 150 7 0 5 20 0 0001 0 0 sp 0 150 7 0 5 20 0
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 1 - .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 129 ++++++------------ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 30 ++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 2 + 4 files changed, 76 insertions(+), 86 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index bd348c1c801b..599b405e754d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -767,7 +767,6 @@ static void hns3_dbg_help(struct hnae3_handle *h) return;
dev_info(&h->pdev->dev, "dump mac tnl status\n"); - dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); }
static void diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 45ccb04100c5..2b7acf620739 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -991,19 +991,42 @@ static int hclge_dbg_dump_tm_pri(struct hclge_dev *hdev, char *buf, int len) return 0; }
+static const struct hclge_dbg_item tm_qset_items[] = { + { "ID", 4 }, + { "MAP_PRI", 2 }, + { "LINK_VLD", 2 }, + { "MODE", 2 }, + { "DWRR", 2 }, + { "IR_B", 2 }, + { "IR_U", 2 }, + { "IR_S", 2 }, + { "BS_B", 2 }, + { "BS_S", 2 }, + { "FLAG", 2 }, + { "RATE(Mbps)", 0 } +}; + static int hclge_dbg_dump_tm_qset(struct hclge_dev *hdev, char *buf, int len) { + char data_str[ARRAY_SIZE(tm_qset_items)][HCLGE_DBG_DATA_STR_LEN]; + char *result[ARRAY_SIZE(tm_qset_items)], *sch_mode_str; u8 priority, link_vld, sch_mode, weight; - char *sch_mode_str; + struct hclge_tm_shaper_para shaper_para; + char content[HCLGE_DBG_TM_INFO_LEN]; + u16 qset_num, i; int ret, pos; - u16 qset_num; - u16 i; + u8 j;
ret = hclge_tm_get_qset_num(hdev, &qset_num); if (ret) return ret;
- pos = scnprintf(buf, len, "ID MAP_PRI LINK_VLD MODE DWRR\n"); + for (i = 0; i < ARRAY_SIZE(tm_qset_items); i++) + result[i] = &data_str[i][0]; + + hclge_dbg_fill_content(content, sizeof(content), tm_qset_items, + NULL, ARRAY_SIZE(tm_qset_items)); + pos = scnprintf(buf, len, "%s", content);
for (i = 0; i < qset_num; i++) { ret = hclge_tm_get_qset_map_pri(hdev, i, &priority, &link_vld); @@ -1018,11 +1041,25 @@ static int hclge_dbg_dump_tm_qset(struct hclge_dev *hdev, char *buf, int len) if (ret) return ret;
+ ret = hclge_tm_get_qset_shaper(hdev, i, &shaper_para); + if (ret) + return ret; + sch_mode_str = sch_mode & HCLGE_TM_TX_SCHD_DWRR_MSK ? "dwrr" : "sp"; - pos += scnprintf(buf + pos, len - pos, - "%04u %4u %1u %4s %3u\n", - i, priority, link_vld, sch_mode_str, weight); + + j = 0; + sprintf(result[j++], "%04u", i); + sprintf(result[j++], "%4u", priority); + sprintf(result[j++], "%4u", link_vld); + sprintf(result[j++], "%4s", sch_mode_str); + sprintf(result[j++], "%3u", weight); + hclge_dbg_fill_shaper_content(&shaper_para, result, &j); + + hclge_dbg_fill_content(content, sizeof(content), tm_qset_items, + (const char **)result, + ARRAY_SIZE(tm_qset_items)); + pos += scnprintf(buf + pos, len - pos, "%s", content); }
return 0; @@ -1787,81 +1824,6 @@ static void hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev) } }
-static void hclge_dbg_dump_qs_shaper_single(struct hclge_dev *hdev, u16 qsid) -{ - struct hclge_qs_shapping_cmd *shap_cfg_cmd; - u8 ir_u, ir_b, ir_s, bs_b, bs_s; - struct hclge_desc desc; - u32 shapping_para; - u32 rate; - int ret; - - hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG, true); - - shap_cfg_cmd = (struct hclge_qs_shapping_cmd *)desc.data; - shap_cfg_cmd->qs_id = cpu_to_le16(qsid); - - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) { - dev_err(&hdev->pdev->dev, - "qs%u failed to get tx_rate, ret=%d\n", - qsid, ret); - return; - } - - shapping_para = le32_to_cpu(shap_cfg_cmd->qs_shapping_para); - ir_b = hclge_tm_get_field(shapping_para, IR_B); - ir_u = hclge_tm_get_field(shapping_para, IR_U); - ir_s = hclge_tm_get_field(shapping_para, IR_S); - bs_b = hclge_tm_get_field(shapping_para, BS_B); - bs_s = hclge_tm_get_field(shapping_para, BS_S); - rate = le32_to_cpu(shap_cfg_cmd->qs_rate); - - dev_info(&hdev->pdev->dev, - "qs%u ir_b:%u, ir_u:%u, ir_s:%u, bs_b:%u, bs_s:%u, flag:%#x, rate:%u(Mbps)\n", - qsid, ir_b, ir_u, ir_s, bs_b, bs_s, shap_cfg_cmd->flag, rate); -} - -static void hclge_dbg_dump_qs_shaper_all(struct hclge_dev *hdev) -{ - struct hnae3_knic_private_info *kinfo; - struct hclge_vport *vport; - int vport_id, i; - - for (vport_id = 0; vport_id <= pci_num_vf(hdev->pdev); vport_id++) { - vport = &hdev->vport[vport_id]; - kinfo = &vport->nic.kinfo; - - dev_info(&hdev->pdev->dev, "qs cfg of vport%d:\n", vport_id); - - for (i = 0; i < kinfo->tc_info.num_tc; i++) { - u16 qsid = vport->qs_offset + i; - - hclge_dbg_dump_qs_shaper_single(hdev, qsid); - } - } -} - -static void hclge_dbg_dump_qs_shaper(struct hclge_dev *hdev, - const char *cmd_buf) -{ - u16 qsid; - int ret; - - ret = kstrtou16(cmd_buf, 0, &qsid); - if (ret) { - hclge_dbg_dump_qs_shaper_all(hdev); - return; - } - - if (qsid >= hdev->ae_dev->dev_specs.max_qset_num) { - dev_err(&hdev->pdev->dev, "qsid(%u) out of range[0-%u]\n", - qsid, hdev->ae_dev->dev_specs.max_qset_num - 1); - return; - } - - hclge_dbg_dump_qs_shaper_single(hdev, qsid); -}
static const struct hclge_dbg_item mac_list_items[] = { { "FUNC_ID", 2 }, @@ -1935,9 +1897,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_serv_info(hdev); } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { hclge_dbg_dump_mac_tnl_status(hdev); - } else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) { - hclge_dbg_dump_qs_shaper(hdev, - &cmd_buf[sizeof("dump qs shaper")]); } else { dev_info(&hdev->pdev->dev, "unknown command\n"); return -EINVAL; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 45870fec0506..78d5bf1ea561 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1733,6 +1733,36 @@ int hclge_tm_get_qset_weight(struct hclge_dev *hdev, u16 qset_id, u8 *weight) return 0; }
+int hclge_tm_get_qset_shaper(struct hclge_dev *hdev, u16 qset_id, + struct hclge_tm_shaper_para *para) +{ + struct hclge_qs_shapping_cmd *shap_cfg_cmd; + struct hclge_desc desc; + u32 shapping_para; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG, true); + shap_cfg_cmd = (struct hclge_qs_shapping_cmd *)desc.data; + shap_cfg_cmd->qs_id = cpu_to_le16(qset_id); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get qset %u shaper, ret = %d\n", qset_id, + ret); + return ret; + } + + shapping_para = le32_to_cpu(shap_cfg_cmd->qs_shapping_para); + para->ir_b = hclge_tm_get_field(shapping_para, IR_B); + para->ir_u = hclge_tm_get_field(shapping_para, IR_U); + para->ir_s = hclge_tm_get_field(shapping_para, IR_S); + para->bs_b = hclge_tm_get_field(shapping_para, BS_B); + para->bs_s = hclge_tm_get_field(shapping_para, BS_S); + para->flag = shap_cfg_cmd->flag; + para->rate = le32_to_cpu(shap_cfg_cmd->qs_rate); + return 0; +} + int hclge_tm_get_pri_sch_mode(struct hclge_dev *hdev, u8 pri_id, u8 *mode) { struct hclge_pri_sch_mode_cfg_cmd *pri_sch_mode; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index d6f148171353..2ee9b795f71d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -237,6 +237,8 @@ int hclge_tm_get_qset_map_pri(struct hclge_dev *hdev, u16 qset_id, u8 *priority, u8 *link_vld); int hclge_tm_get_qset_sch_mode(struct hclge_dev *hdev, u16 qset_id, u8 *mode); int hclge_tm_get_qset_weight(struct hclge_dev *hdev, u16 qset_id, u8 *weight); +int hclge_tm_get_qset_shaper(struct hclge_dev *hdev, u16 qset_id, + struct hclge_tm_shaper_para *para); int hclge_tm_get_pri_sch_mode(struct hclge_dev *hdev, u8 pri_id, u8 *mode); int hclge_tm_get_pri_weight(struct hclge_dev *hdev, u8 pri_id, u8 *weight); int hclge_tm_get_pri_shaper(struct hclge_dev *hdev, u8 pri_id,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 7b07ab06e6b00b4421a4dfd732e98b359e0bad91 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for dump mac tnl status is implemented by "echo xxxx > cmd", and record the information in dmesg. It's unnecessary and heavy. To improve it, create a single file "mac_tnl_status" for it, and query it by command "cat mac_tnl_status", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat mac_tnl_status Recently generated mac tnl interruption: [0111204.175437] status = 0x30 [0154120.329912] status = 0x30
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 12 ++++++---- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 23 +++++++++++++------ 3 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 1fd35e1a1976..49817f3a8bf3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -286,6 +286,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_RX_QUEUE_INFO, HNAE3_DBG_CMD_TX_QUEUE_INFO, HNAE3_DBG_CMD_FD_TCAM, + HNAE3_DBG_CMD_MAC_TNL_STATUS, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 599b405e754d..04c19a0c0e39 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -190,6 +190,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN_128KB, .init = hns3_dbg_common_file_init, }, + { + .name = "mac_tnl_status", + .cmd = HNAE3_DBG_CMD_MAC_TNL_STATUS, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, { .name = "bios_common", .cmd = HNAE3_DBG_CMD_REG_BIOS_COMMON, @@ -762,11 +769,6 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) static void hns3_dbg_help(struct hnae3_handle *h) { dev_info(&h->pdev->dev, "available commands\n"); - - if (!hns3_is_phys_func(h->pdev)) - return; - - dev_info(&h->pdev->dev, "dump mac tnl status\n"); }
static void diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 2b7acf620739..fe7ceab85459 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1807,21 +1807,28 @@ static int hclge_dbg_dump_loopback(struct hclge_dev *hdev, char *buf, int len) /* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt * @hdev: pointer to struct hclge_dev */ -static void hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev) +static int +hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev, char *buf, int len) { #define HCLGE_BILLION_NANO_SECONDS 1000000000
struct hclge_mac_tnl_stats stats; unsigned long rem_nsec; + int pos = 0;
- dev_info(&hdev->pdev->dev, "Recently generated mac tnl interruption:\n"); + pos += scnprintf(buf + pos, len - pos, + "Recently generated mac tnl interruption:\n");
while (kfifo_get(&hdev->mac_tnl_log, &stats)) { rem_nsec = do_div(stats.time, HCLGE_BILLION_NANO_SECONDS); - dev_info(&hdev->pdev->dev, "[%07lu.%03lu] status = 0x%x\n", - (unsigned long)stats.time, rem_nsec / 1000, - stats.status); + + pos += scnprintf(buf + pos, len - pos, + "[%07lu.%03lu] status = 0x%x\n", + (unsigned long)stats.time, rem_nsec / 1000, + stats.status); } + + return 0; }
@@ -1895,8 +1902,6 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
if (strncmp(cmd_buf, "dump serv info", 14) == 0) { hclge_dbg_dump_serv_info(hdev); - } else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) { - hclge_dbg_dump_mac_tnl_status(hdev); } else { dev_info(&hdev->pdev->dev, "unknown command\n"); return -EINVAL; @@ -2026,6 +2031,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_FD_TCAM, .dbg_dump = hclge_dbg_dump_fd_tcam, }, + { + .cmd = HNAE3_DBG_CMD_MAC_TNL_STATUS, + .dbg_dump = hclge_dbg_dump_mac_tnl_status, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit 058c3be95235a12953d6533ef1486dc3d5879688 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, the debugfs command for serv info is implemented by "echo xxxx > cmd", and record the inforamtion in dmesg. It's unnecessary and heavy. To improve it, create a single file "serv_info" for it, and query it by command "cat serv_info", return the result to userspace, rather than record in dmesg.
The display style is below: $ cat service_task_info local_clock: [ 114.203321] delta: 784(ms) last_service_task_processed: 4294918512(jiffies) last_service_task_cnt: 4
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 7 ++++ .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 39 ++++++++++++------- .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 2 + 4 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 49817f3a8bf3..f94649d70191 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -287,6 +287,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_TX_QUEUE_INFO, HNAE3_DBG_CMD_FD_TCAM, HNAE3_DBG_CMD_MAC_TNL_STATUS, + HNAE3_DBG_CMD_SERV_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 04c19a0c0e39..04102d73e89c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -302,6 +302,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "service_task_info", + .cmd = HNAE3_DBG_CMD_SERV_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index fe7ceab85459..e7a043a08685 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1590,12 +1590,26 @@ int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len) return 0; }
-static void hclge_dbg_dump_serv_info(struct hclge_dev *hdev) +static int hclge_dbg_dump_serv_info(struct hclge_dev *hdev, char *buf, int len) { - dev_info(&hdev->pdev->dev, "last_serv_processed: %lu\n", - hdev->last_serv_processed); - dev_info(&hdev->pdev->dev, "last_serv_cnt: %lu\n", - hdev->serv_processed_cnt); + unsigned long rem_nsec; + int pos = 0; + u64 lc; + + lc = local_clock(); + rem_nsec = do_div(lc, HCLGE_BILLION_NANO_SECONDS); + + pos += scnprintf(buf + pos, len - pos, "local_clock: [%5lu.%06lu]\n", + (unsigned long)lc, rem_nsec / 1000); + pos += scnprintf(buf + pos, len - pos, "delta: %u(ms)\n", + jiffies_to_msecs(jiffies - hdev->last_serv_processed)); + pos += scnprintf(buf + pos, len - pos, + "last_service_task_processed: %lu(jiffies)\n", + hdev->last_serv_processed); + pos += scnprintf(buf + pos, len - pos, "last_service_task_cnt: %lu\n", + hdev->serv_processed_cnt); + + return 0; }
static int hclge_dbg_dump_interrupt(struct hclge_dev *hdev, char *buf, int len) @@ -1810,8 +1824,6 @@ static int hclge_dbg_dump_loopback(struct hclge_dev *hdev, char *buf, int len) static int hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev, char *buf, int len) { -#define HCLGE_BILLION_NANO_SECONDS 1000000000 - struct hclge_mac_tnl_stats stats; unsigned long rem_nsec; int pos = 0; @@ -1900,14 +1912,9 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (strncmp(cmd_buf, "dump serv info", 14) == 0) { - hclge_dbg_dump_serv_info(hdev); - } else { - dev_info(&hdev->pdev->dev, "unknown command\n"); - return -EINVAL; - } + dev_info(&hdev->pdev->dev, "unknown command\n");
- return 0; + return -EINVAL; }
static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { @@ -2035,6 +2042,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_MAC_TNL_STATUS, .dbg_dump = hclge_dbg_dump_mac_tnl_status, }, + { + .cmd = HNAE3_DBG_CMD_SERV_INFO, + .dbg_dump = hclge_dbg_dump_serv_info, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index c4956e3d8a41..642752e65a7c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -740,6 +740,8 @@ static const struct hclge_dbg_dfx_message hclge_dbg_tqp_reg[] = { #define HCLGE_DBG_DATA_STR_LEN 32 #define HCLGE_DBG_TM_INFO_LEN 256
+#define HCLGE_BILLION_NANO_SECONDS 1000000000 + struct hclge_dbg_item { char name[HCLGE_DBG_ITEM_NAME_LEN]; u16 interval; /* blank numbers after the item */
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit b4689aaf18633ff1b9ce37b09e226a7964ce9751 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, all debugfs commands have been reconstructed, and the debugfs file node cmd is useless. So remove this debugfs file node.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 - .../ethernet/hisilicon/hns3/hns3_debugfs.c | 106 ------------------ .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 10 -- .../hisilicon/hns3/hns3pf/hclge_main.c | 1 - .../hisilicon/hns3/hns3pf/hclge_main.h | 1 - 5 files changed, 119 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index f94649d70191..286774d06525 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -667,7 +667,6 @@ struct hnae3_ae_ops { void (*enable_fd)(struct hnae3_handle *handle, bool enable); int (*add_arfs_entry)(struct hnae3_handle *handle, u16 queue_id, u16 flow_id, struct flow_keys *fkeys); - int (*dbg_run_cmd)(struct hnae3_handle *handle, const char *cmd_buf); int (*dbg_read_cmd)(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len); pci_ers_result_t (*handle_hw_ras_error)(struct hnae3_ae_dev *ae_dev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 04102d73e89c..57ba5a16ad73 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -773,11 +773,6 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) return 0; }
-static void hns3_dbg_help(struct hnae3_handle *h) -{ - dev_info(&h->pdev->dev, "available commands\n"); -} - static void hns3_dbg_dev_caps(struct hnae3_handle *h, char *buf, int len, int *pos) { @@ -852,97 +847,6 @@ static int hns3_dbg_dev_info(struct hnae3_handle *h, char *buf, int len) return 0; }
-static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, - size_t count, loff_t *ppos) -{ - int uncopy_bytes; - char *buf; - int len; - - if (*ppos != 0) - return 0; - - if (count < HNS3_DBG_READ_LEN) - return -ENOSPC; - - buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len = scnprintf(buf, HNS3_DBG_READ_LEN, "%s\n", - "Please echo help to cmd to get help information"); - uncopy_bytes = copy_to_user(buffer, buf, len); - - kfree(buf); - - if (uncopy_bytes) - return -EFAULT; - - return (*ppos = len); -} - -static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf) -{ - int ret = 0; - - if (strncmp(cmd_buf, "help", 4) == 0) - hns3_dbg_help(handle); - else if (handle->ae_algo->ops->dbg_run_cmd) - ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); - else - ret = -EOPNOTSUPP; - - return ret; -} - -static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, - size_t count, loff_t *ppos) -{ - struct hnae3_handle *handle = filp->private_data; - struct hns3_nic_priv *priv = handle->priv; - char *cmd_buf, *cmd_buf_tmp; - int uncopied_bytes; - int ret; - - if (*ppos != 0) - return 0; - - /* Judge if the instance is being reset. */ - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) - return 0; - - if (count > HNS3_DBG_WRITE_LEN) - return -ENOSPC; - - cmd_buf = kzalloc(count + 1, GFP_KERNEL); - if (!cmd_buf) - return count; - - uncopied_bytes = copy_from_user(cmd_buf, buffer, count); - if (uncopied_bytes) { - kfree(cmd_buf); - return -EFAULT; - } - - cmd_buf[count] = '\0'; - - cmd_buf_tmp = strchr(cmd_buf, '\n'); - if (cmd_buf_tmp) { - *cmd_buf_tmp = '\0'; - count = cmd_buf_tmp - cmd_buf + 1; - } - - ret = hns3_dbg_check_cmd(handle, cmd_buf); - if (ret) - hns3_dbg_help(handle); - - kfree(cmd_buf); - cmd_buf = NULL; - - return count; -} - static int hns3_dbg_get_cmd_index(struct hnae3_handle *handle, const unsigned char *name, u32 *index) { @@ -1071,13 +975,6 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, return ret; }
-static const struct file_operations hns3_dbg_cmd_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = hns3_dbg_cmd_read, - .write = hns3_dbg_cmd_write, -}; - static const struct file_operations hns3_dbg_fops = { .owner = THIS_MODULE, .open = simple_open, @@ -1140,9 +1037,6 @@ int hns3_dbg_init(struct hnae3_handle *handle) debugfs_create_dir(name, hns3_dbgfs_root); handle->hnae3_dbgfs = hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry;
- debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, - &hns3_dbg_cmd_fops); - for (i = 0; i < HNS3_DBG_DENTRY_COMMON; i++) hns3_dbg_dentry[i].dentry = debugfs_create_dir(hns3_dbg_dentry[i].name, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index e7a043a08685..dd9eb6e6f5a7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1907,16 +1907,6 @@ static int hclge_dbg_dump_mac_mc(struct hclge_dev *hdev, char *buf, int len) return 0; }
-int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) -{ - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - - dev_info(&hdev->pdev->dev, "unknown command\n"); - - return -EINVAL; -} - static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { { .cmd = HNAE3_DBG_CMD_TM_NODES, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d4d3f0b247af..3882f829fc49 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -12610,7 +12610,6 @@ static const struct hnae3_ae_ops hclge_ops = { .get_fd_all_rules = hclge_get_all_rules, .enable_fd = hclge_enable_fd, .add_arfs_entry = hclge_add_fd_entry_by_arfs, - .dbg_run_cmd = hclge_dbg_run_cmd, .dbg_read_cmd = hclge_dbg_read_cmd, .handle_hw_ras_error = hclge_handle_hw_ras_error, .get_hw_reset_stat = hclge_get_hw_reset_stat, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 8bf451ef0b05..4bdb0243a97a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1062,7 +1062,6 @@ int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id); int hclge_vport_start(struct hclge_vport *vport); void hclge_vport_stop(struct hclge_vport *vport); int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu); -int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf); int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, char *buf, int len); u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id);
From: Colin Ian King colin.king@canonical.com
mainline inclusion from mainline-master commit 030c8198d744e4149da57bd2a73b87aa6a8aa272 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
In the unlikely event that rule_cnt is zero the variable ret is not assigned a value and function hclge_dbg_dump_fd_tcam can end up returning an unitialized value in ret. Fix this by explicitly setting ret to zero before the for-loop.
Addresses-Coverity: ("Uninitialized scalar variable") Fixes: b5a0b70d77b9 ("net: hns3: refactor dump fd tcam of debugfs") Signed-off-by: Colin Ian King colin.king@canonical.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index dd9eb6e6f5a7..0b7c6838d905 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1519,6 +1519,7 @@ static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len) goto out; }
+ ret = 0; for (i = 0; i < rule_cnt; i++) { tcam_msg.stage = HCLGE_FD_STAGE_1; tcam_msg.loc = rule_locs[i];
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 1e6e76101fd9f51319a742991778bdc3b2d992d9 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, when host set VF untrusted, the driver will disable the promisc mode of VF. It may be conflicted when the VF requests the host to set promisc mode. So refactor it by changing promisc mode for VF asynchronously. With this change, the promisc mode of VF can be restored when the VF being trusted again.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 43 +++++++++++++------ .../hisilicon/hns3/hns3pf/hclge_main.h | 5 ++- .../hisilicon/hns3/hns3pf/hclge_mbx.c | 40 ++++------------- 3 files changed, 42 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3882f829fc49..d37767dc5d85 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11500,10 +11500,7 @@ static int hclge_set_vf_trust(struct hnae3_handle *handle, int vf, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - struct hnae3_ae_dev *ae_dev = hdev->ae_dev; u32 new_trusted = enable ? 1 : 0; - bool en_bc_pmc; - int ret;
vport = hclge_get_vf_vport(hdev, vf); if (!vport) @@ -11512,18 +11509,9 @@ static int hclge_set_vf_trust(struct hnae3_handle *handle, int vf, bool enable) if (vport->vf_info.trusted == new_trusted) return 0;
- /* Disable promisc mode for VF if it is not trusted any more. */ - if (!enable && vport->vf_info.promisc_enable) { - en_bc_pmc = ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2; - ret = hclge_set_vport_promisc_mode(vport, false, false, - en_bc_pmc); - if (ret) - return ret; - vport->vf_info.promisc_enable = 0; - hclge_inform_vf_promisc_info(vport); - } - vport->vf_info.trusted = new_trusted; + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); + hclge_task_schedule(hdev, 0);
return 0; } @@ -12417,6 +12405,7 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) struct hnae3_handle *handle = &vport->nic; u8 tmp_flags; int ret; + u16 i;
if (vport->last_promisc_flags != vport->overflow_promisc_flags) { set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); @@ -12433,6 +12422,32 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) tmp_flags & HNAE3_VLAN_FLTR); } } + + for (i = 1; i < hdev->num_alloc_vport; i++) { + bool uc_en = false; + bool mc_en = false; + bool bc_en; + + vport = &hdev->vport[i]; + + if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, + &vport->state)) + continue; + + if (vport->vf_info.trusted) { + uc_en = vport->vf_info.request_uc_en > 0; + mc_en = vport->vf_info.request_mc_en > 0; + } + bc_en = vport->vf_info.request_bc_en > 0; + + ret = hclge_cmd_set_promisc_mode(hdev, vport->vport_id, uc_en, + mc_en, bc_en); + if (ret) { + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, + &vport->state); + return; + } + } }
static bool hclge_module_existed(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 4bdb0243a97a..8425dae9e8b0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -952,6 +952,7 @@ struct hclge_rss_tuple_cfg { enum HCLGE_VPORT_STATE { HCLGE_VPORT_STATE_ALIVE, HCLGE_VPORT_STATE_MAC_TBL_CHANGE, + HCLGE_VPORT_STATE_PROMISC_CHANGE, HCLGE_VPORT_STATE_MAX };
@@ -972,7 +973,9 @@ struct hclge_vf_info { u32 spoofchk; u32 max_tx_rate; u32 trusted; - u16 promisc_enable; + u8 request_uc_en; + u8 request_mc_en; + u8 request_bc_en; };
struct hclge_vport { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index f1c9f4ada348..851408bcbc4f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -231,19 +231,15 @@ static int hclge_map_unmap_ring_to_vf_vector(struct hclge_vport *vport, bool en, return ret; }
-static int hclge_set_vf_promisc_mode(struct hclge_vport *vport, - struct hclge_mbx_vf_to_pf_cmd *req) +static void hclge_set_vf_promisc_mode(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *req) { - bool en_bc = req->msg.en_bc ? true : false; - bool en_uc = req->msg.en_uc ? true : false; - bool en_mc = req->msg.en_mc ? true : false; struct hnae3_handle *handle = &vport->nic; - int ret; + struct hclge_dev *hdev = vport->back;
- if (!vport->vf_info.trusted) { - en_uc = false; - en_mc = false; - } + vport->vf_info.request_uc_en = req->msg.en_uc; + vport->vf_info.request_mc_en = req->msg.en_mc; + vport->vf_info.request_bc_en = req->msg.en_bc;
if (req->msg.en_limit_promisc) set_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->priv_flags); @@ -251,22 +247,8 @@ static int hclge_set_vf_promisc_mode(struct hclge_vport *vport, clear_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->priv_flags);
- ret = hclge_set_vport_promisc_mode(vport, en_uc, en_mc, en_bc); - - vport->vf_info.promisc_enable = (en_uc || en_mc) ? 1 : 0; - - return ret; -} - -void hclge_inform_vf_promisc_info(struct hclge_vport *vport) -{ - u8 dest_vfid = (u8)vport->vport_id; - u8 msg_data[2]; - - memcpy(&msg_data[0], &vport->vf_info.promisc_enable, sizeof(u16)); - - hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), - HCLGE_MBX_PUSH_PROMISC_INFO, dest_vfid); + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); + hclge_task_schedule(hdev, 0); }
static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport, @@ -750,11 +732,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev) req); break; case HCLGE_MBX_SET_PROMISC_MODE: - ret = hclge_set_vf_promisc_mode(vport, req); - if (ret) - dev_err(&hdev->pdev->dev, - "PF fail(%d) to set VF promisc mode\n", - ret); + hclge_set_vf_promisc_mode(vport, req); break; case HCLGE_MBX_SET_UNICAST: ret = hclge_set_vf_uc_mac_addr(vport, req);
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 4e2471f7b6ef5a564cd05bc5fb9f3ce71b7b7942 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, PF is using HCLGE_STATE_PROMISC_CHANGED to indicate need synchronize the promisc mode for itself, and using flag HCLGE_VPORT_STATE_PROMISC_CHANGE for its VF. To keep consistent, remove flag HCLGE_STATE_PROMISC_CHANGED, and use flag HCLGE_VPORT_STATE_PROMISC_CHANGE instead.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 12 ++++++------ .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 - 2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d37767dc5d85..6addeb299bba 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5183,9 +5183,8 @@ static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc, static void hclge_request_update_promisc_mode(struct hnae3_handle *handle) { struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back;
- set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); }
static void hclge_sync_fd_state(struct hclge_dev *hdev) @@ -8050,6 +8049,7 @@ int hclge_vport_start(struct hclge_vport *vport) struct hclge_dev *hdev = vport->back;
set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); vport->last_active_jiffies = jiffies;
if (test_bit(vport->vport_id, hdev->vport_config_block)) { @@ -10048,7 +10048,6 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev)
hclge_restore_mac_table_common(vport); hclge_restore_vport_vlan_table(vport); - set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); set_bit(HCLGE_STATE_FD_USER_DEF_CHANGED, &hdev->state); hclge_restore_fd_entries(handle); } @@ -12408,16 +12407,17 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) u16 i;
if (vport->last_promisc_flags != vport->overflow_promisc_flags) { - set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); vport->last_promisc_flags = vport->overflow_promisc_flags; }
- if (test_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state)) { + if (test_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state)) { tmp_flags = handle->netdev_flags | vport->last_promisc_flags; ret = hclge_set_promisc_mode(handle, tmp_flags & HNAE3_UPE, tmp_flags & HNAE3_MPE); if (!ret) { - clear_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state); + clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, + &vport->state); hclge_enable_vlan_filter(handle, tmp_flags & HNAE3_VLAN_FLTR); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 8425dae9e8b0..9e4d02d73bf3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -224,7 +224,6 @@ enum HCLGE_DEV_STATE { HCLGE_STATE_STATISTICS_UPDATING, HCLGE_STATE_CMD_DISABLE, HCLGE_STATE_LINK_UPDATING, - HCLGE_STATE_PROMISC_CHANGED, HCLGE_STATE_RST_FAIL, HCLGE_STATE_FD_TBL_CHANGED, HCLGE_STATE_FD_CLEAR_ALL,
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 307ea4ce3edd3f7d1130d3c35955aa77063296cc category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The Linux kernel has support for a dynamic interrupt moderation algorithm known as "dimlib". Replace the custom driver-specific implementation of dynamic interrupt moderation with the kernel's algorithm.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/Kconfig | 1 + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 193 +++++++----------- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 4 +- 3 files changed, 73 insertions(+), 125 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index 44f9279cdde1..fa6025dc4cdb 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -130,6 +130,7 @@ config HNS3_ENET default m depends on 64BIT && PCI depends on INET + select DIMLIB help This selects the Ethernet Driver for Hisilicon Network Subsystem 3 for hip08 family of SoCs. This module depends upon HNAE3 driver to access the HNAE3 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 87b037c88ca5..43dcf3f0dbe2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -368,6 +368,7 @@ static irqreturn_t hns3_irq_handle(int irq, void *vector) struct hns3_enet_tqp_vector *tqp_vector = vector;
napi_schedule_irqoff(&tqp_vector->napi); + tqp_vector->event_cnt++;
return IRQ_HANDLED; } @@ -471,6 +472,8 @@ static void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector)
disable_irq(tqp_vector->vector_irq); napi_disable(&tqp_vector->napi); + cancel_work_sync(&tqp_vector->rx_group.dim.work); + cancel_work_sync(&tqp_vector->tx_group.dim.work); }
void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector, @@ -3763,139 +3766,30 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget, return recv_pkts; }
-static bool hns3_get_new_flow_lvl(struct hns3_enet_ring_group *ring_group) +static void hns3_update_rx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector) { -#define HNS3_RX_LOW_BYTE_RATE 10000 -#define HNS3_RX_MID_BYTE_RATE 20000 -#define HNS3_RX_ULTRA_PACKET_RATE 40 - - enum hns3_flow_level_range new_flow_level; - struct hns3_enet_tqp_vector *tqp_vector; - int packets_per_msecs, bytes_per_msecs; - u32 time_passed_ms; - - tqp_vector = ring_group->ring->tqp_vector; - time_passed_ms = - jiffies_to_msecs(jiffies - tqp_vector->last_jiffies); - if (!time_passed_ms) - return false; - - do_div(ring_group->total_packets, time_passed_ms); - packets_per_msecs = ring_group->total_packets; - - do_div(ring_group->total_bytes, time_passed_ms); - bytes_per_msecs = ring_group->total_bytes; - - new_flow_level = ring_group->coal.flow_level; - - /* Simple throttlerate management - * 0-10MB/s lower (50000 ints/s) - * 10-20MB/s middle (20000 ints/s) - * 20-1249MB/s high (18000 ints/s) - * > 40000pps ultra (8000 ints/s) - */ - switch (new_flow_level) { - case HNS3_FLOW_LOW: - if (bytes_per_msecs > HNS3_RX_LOW_BYTE_RATE) - new_flow_level = HNS3_FLOW_MID; - break; - case HNS3_FLOW_MID: - if (bytes_per_msecs > HNS3_RX_MID_BYTE_RATE) - new_flow_level = HNS3_FLOW_HIGH; - else if (bytes_per_msecs <= HNS3_RX_LOW_BYTE_RATE) - new_flow_level = HNS3_FLOW_LOW; - break; - case HNS3_FLOW_HIGH: - case HNS3_FLOW_ULTRA: - default: - if (bytes_per_msecs <= HNS3_RX_MID_BYTE_RATE) - new_flow_level = HNS3_FLOW_MID; - break; - } - - if (packets_per_msecs > HNS3_RX_ULTRA_PACKET_RATE && - &tqp_vector->rx_group == ring_group) - new_flow_level = HNS3_FLOW_ULTRA; - - ring_group->total_bytes = 0; - ring_group->total_packets = 0; - ring_group->coal.flow_level = new_flow_level; - - return true; -} - -static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group) -{ - struct hns3_enet_tqp_vector *tqp_vector; - u16 new_int_gl; - - if (!ring_group->ring) - return false; - - tqp_vector = ring_group->ring->tqp_vector; - if (!tqp_vector->last_jiffies) - return false; - - if (ring_group->total_packets == 0) { - ring_group->coal.int_gl = HNS3_INT_GL_50K; - ring_group->coal.flow_level = HNS3_FLOW_LOW; - return true; - } - - if (!hns3_get_new_flow_lvl(ring_group)) - return false; + struct hns3_enet_ring_group *rx_group = &tqp_vector->rx_group; + struct dim_sample sample = {};
- new_int_gl = ring_group->coal.int_gl; - switch (ring_group->coal.flow_level) { - case HNS3_FLOW_LOW: - new_int_gl = HNS3_INT_GL_50K; - break; - case HNS3_FLOW_MID: - new_int_gl = HNS3_INT_GL_20K; - break; - case HNS3_FLOW_HIGH: - new_int_gl = HNS3_INT_GL_18K; - break; - case HNS3_FLOW_ULTRA: - new_int_gl = HNS3_INT_GL_8K; - break; - default: - break; - } + if (!rx_group->coal.adapt_enable) + return;
- if (new_int_gl != ring_group->coal.int_gl) { - ring_group->coal.int_gl = new_int_gl; - return true; - } - return false; + dim_update_sample(tqp_vector->event_cnt, rx_group->total_packets, + rx_group->total_bytes, &sample); + net_dim(&rx_group->dim, sample); }
-static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector) +static void hns3_update_tx_int_coalesce(struct hns3_enet_tqp_vector *tqp_vector) { - struct hns3_enet_ring_group *rx_group = &tqp_vector->rx_group; struct hns3_enet_ring_group *tx_group = &tqp_vector->tx_group; - bool rx_update, tx_update; + struct dim_sample sample = {};
- /* update param every 1000ms */ - if (time_before(jiffies, - tqp_vector->last_jiffies + msecs_to_jiffies(1000))) + if (!tx_group->coal.adapt_enable) return;
- if (rx_group->coal.adapt_enable) { - rx_update = hns3_get_new_int_gl(rx_group); - if (rx_update) - hns3_set_vector_coalesce_rx_gl(tqp_vector, - rx_group->coal.int_gl); - } - - if (tx_group->coal.adapt_enable) { - tx_update = hns3_get_new_int_gl(tx_group); - if (tx_update) - hns3_set_vector_coalesce_tx_gl(tqp_vector, - tx_group->coal.int_gl); - } - - tqp_vector->last_jiffies = jiffies; + dim_update_sample(tqp_vector->event_cnt, tx_group->total_packets, + tx_group->total_bytes, &sample); + net_dim(&tx_group->dim, sample); }
static int hns3_nic_common_poll(struct napi_struct *napi, int budget) @@ -3940,7 +3834,9 @@ static int hns3_nic_common_poll(struct napi_struct *napi, int budget)
if (napi_complete(napi) && likely(!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))) { - hns3_update_new_int_gl(tqp_vector); + hns3_update_rx_int_coalesce(tqp_vector); + hns3_update_tx_int_coalesce(tqp_vector); + hns3_mask_vector_irq(tqp_vector, 1); }
@@ -4071,6 +3967,54 @@ static void hns3_nic_set_cpumask(struct hns3_nic_priv *priv) } }
+static void hns3_rx_dim_work(struct work_struct *work) +{ + struct dim *dim = container_of(work, struct dim, work); + struct hns3_enet_ring_group *group = container_of(dim, + struct hns3_enet_ring_group, dim); + struct hns3_enet_tqp_vector *tqp_vector = group->ring->tqp_vector; + struct dim_cq_moder cur_moder = + net_dim_get_rx_moderation(dim->mode, dim->profile_ix); + + hns3_set_vector_coalesce_rx_gl(group->ring->tqp_vector, cur_moder.usec); + tqp_vector->rx_group.coal.int_gl = cur_moder.usec; + + if (cur_moder.pkts < tqp_vector->rx_group.coal.int_ql_max) { + hns3_set_vector_coalesce_rx_ql(tqp_vector, cur_moder.pkts); + tqp_vector->rx_group.coal.int_ql = cur_moder.pkts; + } + + dim->state = DIM_START_MEASURE; +} + +static void hns3_tx_dim_work(struct work_struct *work) +{ + struct dim *dim = container_of(work, struct dim, work); + struct hns3_enet_ring_group *group = container_of(dim, + struct hns3_enet_ring_group, dim); + struct hns3_enet_tqp_vector *tqp_vector = group->ring->tqp_vector; + struct dim_cq_moder cur_moder = + net_dim_get_tx_moderation(dim->mode, dim->profile_ix); + + hns3_set_vector_coalesce_tx_gl(tqp_vector, cur_moder.usec); + tqp_vector->tx_group.coal.int_gl = cur_moder.usec; + + if (cur_moder.pkts < tqp_vector->tx_group.coal.int_ql_max) { + hns3_set_vector_coalesce_tx_ql(tqp_vector, cur_moder.pkts); + tqp_vector->tx_group.coal.int_ql = cur_moder.pkts; + } + + dim->state = DIM_START_MEASURE; +} + +static void hns3_nic_init_dim(struct hns3_enet_tqp_vector *tqp_vector) +{ + INIT_WORK(&tqp_vector->rx_group.dim.work, hns3_rx_dim_work); + tqp_vector->rx_group.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; + INIT_WORK(&tqp_vector->tx_group.dim.work, hns3_tx_dim_work); + tqp_vector->tx_group.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; +} + static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv) { struct hnae3_handle *h = priv->ae_handle; @@ -4084,6 +4028,7 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv) tqp_vector = &priv->tqp_vector[i]; hns3_vector_coalesce_init_hw(tqp_vector, priv); tqp_vector->num_tqps = 0; + hns3_nic_init_dim(tqp_vector); }
for (i = 0; i < h->kinfo.num_tqps; i++) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 79ff2fa61d47..b038441907f9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -4,6 +4,7 @@ #ifndef __HNS3_ENET_H #define __HNS3_ENET_H
+#include <linux/dim.h> #include <linux/if_vlan.h>
#include "hnae3.h" @@ -482,6 +483,7 @@ struct hns3_enet_ring_group { u64 total_packets; /* total packets processed this group */ u16 count; struct hns3_enet_coalesce coal; + struct dim dim; };
struct hns3_enet_tqp_vector { @@ -503,7 +505,7 @@ struct hns3_enet_tqp_vector {
char name[HNAE3_INT_NAME_LEN];
- unsigned long last_jiffies; + u64 event_cnt; } ____cacheline_internodealigned_in_smp;
struct hns3_nic_priv {
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit b44eb28d44a65370e77d0bcd9a87cee3fa1daaca category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, option "qos" is igored by HNS3 driver for command "ip link set ethx vf <vf id> vlan <vlan id> qos <qos value>". Add support for it.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 91 +++++++++++++------ 1 file changed, 63 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6addeb299bba..af5b278a0643 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -9724,7 +9724,7 @@ static int hclge_set_vlan_rx_offload_cfg(struct hclge_vport *vport)
static int hclge_vlan_offload_cfg(struct hclge_vport *vport, u16 port_base_vlan_state, - u16 vlan_tag) + u16 vlan_tag, u8 qos) { int ret;
@@ -9738,7 +9738,8 @@ static int hclge_vlan_offload_cfg(struct hclge_vport *vport, vport->txvlan_cfg.accept_tag1 = ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3; vport->txvlan_cfg.insert_tag1_en = true; - vport->txvlan_cfg.default_tag1 = vlan_tag; + vport->txvlan_cfg.default_tag1 = (qos << VLAN_PRIO_SHIFT) | + vlan_tag; }
vport->txvlan_cfg.accept_untag1 = true; @@ -9867,13 +9868,15 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
for (i = 0; i < hdev->num_alloc_vport; i++) { u16 vlan_tag; + u8 qos;
vport = &hdev->vport[i]; vlan_tag = vport->port_base_vlan_cfg.vlan_info.vlan_tag; + qos = vport->port_base_vlan_cfg.vlan_info.qos;
ret = hclge_vlan_offload_cfg(vport, vport->port_base_vlan_cfg.state, - vlan_tag); + vlan_tag, qos); if (ret) return ret; } @@ -10084,6 +10087,10 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport,
if (port_base_vlan_state == HNAE3_PORT_BASE_VLAN_ENABLE) { hclge_rm_vport_all_vlan_table(vport, false); + /* force clear VLAN 0 */ + ret = hclge_set_vf_vlan_common(hdev, vport->vport_id, true, 0); + if (ret) + return ret; return hclge_set_vlan_filter_hw(hdev, htons(new_info->vlan_proto), vport->vport_id, @@ -10091,6 +10098,11 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport, false); }
+ /* force add VLAN 0 */ + ret = hclge_set_vf_vlan_common(hdev, vport->vport_id, false, 0); + if (ret) + return ret; + ret = hclge_set_vlan_filter_hw(hdev, htons(old_info->vlan_proto), vport->vport_id, old_info->vlan_tag, true); @@ -10100,6 +10112,18 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport, return hclge_add_vport_all_vlan_table(vport); }
+static bool hclge_need_update_vlan_filter(const struct hclge_vlan_info *new_cfg, + const struct hclge_vlan_info *old_cfg) +{ + if (new_cfg->vlan_tag != old_cfg->vlan_tag) + return true; + + if (new_cfg->vlan_tag == 0 && (new_cfg->qos == 0 || old_cfg->qos == 0)) + return true; + + return false; +} + int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, struct hclge_vlan_info *vlan_info) { @@ -10110,10 +10134,14 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
old_vlan_info = &vport->port_base_vlan_cfg.vlan_info;
- ret = hclge_vlan_offload_cfg(vport, state, vlan_info->vlan_tag); + ret = hclge_vlan_offload_cfg(vport, state, vlan_info->vlan_tag, + vlan_info->qos); if (ret) return ret;
+ if (!hclge_need_update_vlan_filter(vlan_info, old_vlan_info)) + goto out; + if (state == HNAE3_PORT_BASE_VLAN_MODIFY) { /* add new VLAN tag */ ret = hclge_set_vlan_filter_hw(hdev, @@ -10125,15 +10153,23 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, return ret;
/* remove old VLAN tag */ - ret = hclge_set_vlan_filter_hw(hdev, - htons(old_vlan_info->vlan_proto), - vport->vport_id, - old_vlan_info->vlan_tag, - true); - if (ret) + if (old_vlan_info->vlan_tag == 0) + ret = hclge_set_vf_vlan_common(hdev, vport->vport_id, + true, 0); + else + ret = hclge_set_vlan_filter_hw(hdev, + htons(ETH_P_8021Q), + vport->vport_id, + old_vlan_info->vlan_tag, + true); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to clear vport%u port base vlan %u, ret = %d.\n", + vport->vport_id, old_vlan_info->vlan_tag, ret); return ret; + }
- goto update; + goto out; }
ret = hclge_update_vlan_filter_entries(vport, state, vlan_info, @@ -10141,38 +10177,37 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, if (ret) return ret;
- /* update state only when disable/enable port based VLAN */ +out: vport->port_base_vlan_cfg.state = state; if (state == HNAE3_PORT_BASE_VLAN_DISABLE) nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_DISABLE; else nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
-update: - vport->port_base_vlan_cfg.vlan_info.vlan_tag = vlan_info->vlan_tag; - vport->port_base_vlan_cfg.vlan_info.qos = vlan_info->qos; - vport->port_base_vlan_cfg.vlan_info.vlan_proto = vlan_info->vlan_proto; + vport->port_base_vlan_cfg.vlan_info = *vlan_info;
return 0; }
static u16 hclge_get_port_base_vlan_state(struct hclge_vport *vport, enum hnae3_port_base_vlan_state state, - u16 vlan) + u16 vlan, u8 qos) { if (state == HNAE3_PORT_BASE_VLAN_DISABLE) { - if (!vlan) + if (!vlan && !qos) return HNAE3_PORT_BASE_VLAN_NOCHANGE; - else - return HNAE3_PORT_BASE_VLAN_ENABLE; - } else { - if (!vlan) - return HNAE3_PORT_BASE_VLAN_DISABLE; - else if (vport->port_base_vlan_cfg.vlan_info.vlan_tag == vlan) - return HNAE3_PORT_BASE_VLAN_NOCHANGE; - else - return HNAE3_PORT_BASE_VLAN_MODIFY; + + return HNAE3_PORT_BASE_VLAN_ENABLE; } + + if (!vlan && !qos) + return HNAE3_PORT_BASE_VLAN_DISABLE; + + if (vport->port_base_vlan_cfg.vlan_info.vlan_tag == vlan && + vport->port_base_vlan_cfg.vlan_info.qos == qos) + return HNAE3_PORT_BASE_VLAN_NOCHANGE; + + return HNAE3_PORT_BASE_VLAN_MODIFY; }
static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid, @@ -10200,7 +10235,7 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
state = hclge_get_port_base_vlan_state(vport, vport->port_base_vlan_cfg.state, - vlan); + vlan, qos); if (state == HNAE3_PORT_BASE_VLAN_NOCHANGE) return 0;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit f2dbf0ed4e0c1789cc7c74ab3798bd0cdb7a2bf1 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Use struct "hclge_vlan_info" instead of separately parameters for function hclge_push_vf_port_base_vlan_info(), to make it more concise.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +-- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 4 ++-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 10 +++++----- 3 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index af5b278a0643..7c6b51f8d2b0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -10258,8 +10258,7 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid, test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) hclge_push_vf_port_base_vlan_info(&hdev->vport[0], vport->vport_id, state, - vlan, qos, - ntohs(proto)); + &vlan_info);
return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 9e4d02d73bf3..e3dc2167ebd9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1084,8 +1084,8 @@ void hclge_restore_vport_vlan_table(struct hclge_vport *vport); int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, struct hclge_vlan_info *vlan_info); int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, - u16 state, u16 vlan_tag, u16 qos, - u16 vlan_proto); + u16 state, + struct hclge_vlan_info *vlan_info); void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time); int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 851408bcbc4f..16b42cee778e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -318,17 +318,17 @@ static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport, }
int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, - u16 state, u16 vlan_tag, u16 qos, - u16 vlan_proto) + u16 state, + struct hclge_vlan_info *vlan_info) { #define MSG_DATA_SIZE 8
u8 msg_data[MSG_DATA_SIZE];
memcpy(&msg_data[0], &state, sizeof(u16)); - memcpy(&msg_data[2], &vlan_proto, sizeof(u16)); - memcpy(&msg_data[4], &qos, sizeof(u16)); - memcpy(&msg_data[6], &vlan_tag, sizeof(u16)); + memcpy(&msg_data[2], &vlan_info->vlan_proto, sizeof(u16)); + memcpy(&msg_data[4], &vlan_info->qos, sizeof(u16)); + memcpy(&msg_data[6], &vlan_info->vlan_tag, sizeof(u16));
return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), HCLGE_MBX_PUSH_VLAN_INFO, vfid);
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 132023de7149e7dde4b457328cb233dc58561b54 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
For the PF have called hclge_update_port_base_vlan_cfg() already before notify VF, it's unnecessary to update port based VLAN again when received mailbox request from VF.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 9 --------- 1 file changed, 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 16b42cee778e..3f7d1f2cbe2d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -360,15 +360,6 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport, bool en = msg_cmd->is_kill ? true : false;
status = hclge_en_hw_strip_rxvtag(handle, en); - } else if (msg_cmd->subcode == HCLGE_MBX_PORT_BASE_VLAN_CFG) { - struct hclge_vlan_info *vlan_info; - u16 *state; - - state = (u16 *)&mbx_req->msg.data[HCLGE_MBX_VLAN_STATE_OFFSET]; - vlan_info = (struct hclge_vlan_info *) - &mbx_req->msg.data[HCLGE_MBX_VLAN_INFO_OFFSET]; - status = hclge_update_port_base_vlan_cfg(vport, *state, - vlan_info); } else if (msg_cmd->subcode == HCLGE_MBX_GET_PORT_BASE_VLAN_STATE) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(vport->nic.pdev); /* vf does not need to know about the port based VLAN state
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 060e9accaa743d701e653213651cf3feee1ae921 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
The struct hclge_vf_vlan_cfg is firstly designed for setting VLAN filter tag. And it's reused for enable RX VLAN offload later. It's strange to use member "is_kill" to indicate "enable". So redefine the struct hclge_vf_vlan_cfg to adapt it.
For there are already 3 subcodes being used in function hclge_set_vf_vlan_cfg(), use "switch-case" style for each branch, rather than "if-else". Also simplify the assignment for each branch to make it more clearly.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.h | 11 ++++-- .../hisilicon/hns3/hns3pf/hclge_mbx.c | 35 ++++++++----------- 2 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index e3dc2167ebd9..cd1e40152a67 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -759,9 +759,14 @@ struct hclge_mac_tnl_stats { struct hclge_vf_vlan_cfg { u8 mbx_cmd; u8 subcode; - u8 is_kill; - u16 vlan; - u16 proto; + union { + struct { + u8 is_kill; + u16 vlan; + u16 proto; + }; + u8 enable; + }; };
#pragma pack() diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 3f7d1f2cbe2d..54eee94df47a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -341,40 +341,33 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport, #define HCLGE_MBX_VLAN_STATE_OFFSET 0 #define HCLGE_MBX_VLAN_INFO_OFFSET 2
+ struct hnae3_handle *handle = &vport->nic; + struct hclge_dev *hdev = vport->back; struct hclge_vf_vlan_cfg *msg_cmd; - int status = 0;
msg_cmd = (struct hclge_vf_vlan_cfg *)&mbx_req->msg; - if (msg_cmd->subcode == HCLGE_MBX_VLAN_FILTER) { - struct hnae3_handle *handle = &vport->nic; - u16 vlan, proto; - bool is_kill; - - is_kill = !!msg_cmd->is_kill; - vlan = msg_cmd->vlan; - proto = msg_cmd->proto; - status = hclge_set_vlan_filter(handle, cpu_to_be16(proto), - vlan, is_kill); - } else if (msg_cmd->subcode == HCLGE_MBX_VLAN_RX_OFF_CFG) { - struct hnae3_handle *handle = &vport->nic; - bool en = msg_cmd->is_kill ? true : false; - - status = hclge_en_hw_strip_rxvtag(handle, en); - } else if (msg_cmd->subcode == HCLGE_MBX_GET_PORT_BASE_VLAN_STATE) { - struct hnae3_ae_dev *ae_dev = pci_get_drvdata(vport->nic.pdev); + switch (msg_cmd->subcode) { + case HCLGE_MBX_VLAN_FILTER: + return hclge_set_vlan_filter(handle, + cpu_to_be16(msg_cmd->proto), + msg_cmd->vlan, msg_cmd->is_kill); + case HCLGE_MBX_VLAN_RX_OFF_CFG: + return hclge_en_hw_strip_rxvtag(handle, msg_cmd->enable); + case HCLGE_MBX_GET_PORT_BASE_VLAN_STATE: /* vf does not need to know about the port based VLAN state * on device HNAE3_DEVICE_VERSION_V3. So always return disable * on device HNAE3_DEVICE_VERSION_V3 if vf queries the port * based VLAN state. */ resp_msg->data[0] = - ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3 ? + hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3 ? HNAE3_PORT_BASE_VLAN_DISABLE : vport->port_base_vlan_cfg.state; resp_msg->len = sizeof(u8); + return 0; + default: + return 0; } - - return status; }
static int hclge_set_vf_alive(struct hclge_vport *vport,
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 2ba306627f5950c9a7850f3b0499d39e522dc249 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Previously, with hardware limitation, the port VLAN filter are effective for both PF and its VFs simultaneously, so a single function is not able to enable/disable separately, and the VLAN filter state is default enabled. Now some device supports each function to bypass port VLAN filter, then each function can switch VLAN filter separately. Add capability flag to check whether the device supports modify VLAN filter state. If flag on, user will be able to modify the VLAN filter state by ethtool -K.
Furtherly, the default VLAN filter state is also changed according to whether non-zero VLAN used. Then the device can receive packet with any VLAN tag if only VLAN 0 used.
The function hclge_need_enable_vport_vlan_filter() is used to help implement above changes. And the VLAN filter handle for promisc mode can also be simplified by this function.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 5 +- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 8 +- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 39 ++-- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 1 - .../ethernet/hisilicon/hns3/hns3_ethtool.c | 8 +- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 4 + .../hisilicon/hns3/hns3pf/hclge_cmd.h | 12 ++ .../hisilicon/hns3/hns3pf/hclge_main.c | 183 ++++++++++++++++-- .../hisilicon/hns3/hns3pf/hclge_main.h | 8 + 9 files changed, 214 insertions(+), 54 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 286774d06525..5aeda231a683 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -91,6 +91,8 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, HNAE3_DEV_SUPPORT_PAUSE_B, HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, + HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, + HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, };
#define hnae3_dev_fd_supported(hdev) \ @@ -630,7 +632,7 @@ struct hnae3_ae_ops { void (*get_mdix_mode)(struct hnae3_handle *handle, u8 *tp_mdix_ctrl, u8 *tp_mdix);
- void (*enable_vlan_filter)(struct hnae3_handle *handle, bool enable); + int (*enable_vlan_filter)(struct hnae3_handle *handle, bool enable); int (*set_vlan_filter)(struct hnae3_handle *handle, __be16 proto, u16 vlan_id, bool is_kill); int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid, @@ -782,7 +784,6 @@ struct hnae3_roce_private_info { #define HNAE3_BPE BIT(2) /* broadcast promisc enable */ #define HNAE3_OVERFLOW_UPE BIT(3) /* unicast mac vlan overflow */ #define HNAE3_OVERFLOW_MPE BIT(4) /* multicast mac vlan overflow */ -#define HNAE3_VLAN_FLTR BIT(5) /* enable vlan filter */ #define HNAE3_UPE (HNAE3_USER_UPE | HNAE3_OVERFLOW_UPE) #define HNAE3_MPE (HNAE3_USER_MPE | HNAE3_OVERFLOW_MPE)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 57ba5a16ad73..3feba43586e0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -345,7 +345,13 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { }, { .name = "support rxd advanced layout", .cap_bit = HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, - }, + }, { + .name = "support port vlan bypass", + .cap_bit = HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, + }, { + .name = "support modify vlan filter state", + .cap_bit = HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, + } };
static void hns3_dbg_fill_content(char *content, u16 len, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 43dcf3f0dbe2..393979bec170 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -908,13 +908,10 @@ static u8 hns3_get_netdev_flags(struct net_device *netdev) { u8 flags = 0;
- if (netdev->flags & IFF_PROMISC) { + if (netdev->flags & IFF_PROMISC) flags = HNAE3_USER_UPE | HNAE3_USER_MPE | HNAE3_BPE; - } else { - flags |= HNAE3_VLAN_FLTR; - if (netdev->flags & IFF_ALLMULTI) - flags |= HNAE3_USER_MPE; - } + else if (netdev->flags & IFF_ALLMULTI) + flags = HNAE3_USER_MPE;
return flags; } @@ -944,25 +941,6 @@ void hns3_request_update_promisc_mode(struct hnae3_handle *handle) ops->request_update_promisc_mode(handle); }
-void hns3_enable_vlan_filter(struct net_device *netdev, bool enable) -{ - struct hns3_nic_priv *priv = netdev_priv(netdev); - struct hnae3_handle *h = priv->ae_handle; - struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); - bool last_state; - - if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2 && - h->ae_algo->ops->enable_vlan_filter) { - last_state = h->netdev_flags & HNAE3_VLAN_FLTR ? true : false; - if (enable != last_state) { - netdev_info(netdev, - "%s vlan filter\n", - enable ? "enable" : "disable"); - h->ae_algo->ops->enable_vlan_filter(h, enable); - } - } -} - static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, u16 *mss, u32 *type_cs_vlan_tso, u32 *send_bytes) { @@ -1980,6 +1958,14 @@ static int hns3_nic_set_features(struct net_device *netdev, return -EINVAL; }
+ if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) && + h->ae_algo->ops->enable_vlan_filter) { + enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER); + ret = h->ae_algo->ops->enable_vlan_filter(h, enable); + if (ret) + return ret; + } + netdev->features = features; return 0; } @@ -2825,6 +2811,9 @@ static void hns3_set_default_feature(struct net_device *netdev) netdev->hw_features |= NETIF_F_HW_TC; netdev->features |= NETIF_F_HW_TC; } + + if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; }
static int hns3_alloc_buffer(struct hns3_enet_ring *ring, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index b038441907f9..5698a14a804e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -643,7 +643,6 @@ void hns3_set_vector_coalesce_rx_ql(struct hns3_enet_tqp_vector *tqp_vector, void hns3_set_vector_coalesce_tx_ql(struct hns3_enet_tqp_vector *tqp_vector, u32 ql_value);
-void hns3_enable_vlan_filter(struct net_device *netdev, bool enable); void hns3_request_update_promisc_mode(struct hnae3_handle *handle);
#ifdef CONFIG_HNS3_DCB diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index c1ea403d2b56..bb7c2ec7ed6f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -88,7 +88,6 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) { struct hnae3_handle *h = hns3_get_handle(ndev); struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); - bool vlan_filter_enable; int ret;
if (!h->ae_algo->ops->set_loopback || @@ -110,14 +109,11 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) if (ret || ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) return ret;
- if (en) { + if (en) h->ae_algo->ops->set_promisc_mode(h, true, true); - } else { + else /* recover promisc mode before loopback test */ hns3_request_update_promisc_mode(h); - vlan_filter_enable = ndev->flags & IFF_PROMISC ? false : true; - hns3_enable_vlan_filter(ndev, vlan_filter_enable); - }
return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 6aed30cc22f2..8f6ed8577aea 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -388,6 +388,10 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_RXD_ADV_LAYOUT_B)) set_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGE_CAP_PORT_VLAN_BYPASS_B)) { + set_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, ae_dev->caps); + set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps); + } }
static __le32 hclge_build_api_caps(void) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 12558aa0fe0a..da78a6477e46 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -236,6 +236,7 @@ enum hclge_opcode_type { HCLGE_OPC_VLAN_FILTER_CTRL = 0x1100, HCLGE_OPC_VLAN_FILTER_PF_CFG = 0x1101, HCLGE_OPC_VLAN_FILTER_VF_CFG = 0x1102, + HCLGE_OPC_PORT_VLAN_BYPASS = 0x1103,
/* Flow Director commands */ HCLGE_OPC_FD_MODE_CTRL = 0x1200, @@ -392,6 +393,7 @@ enum HCLGE_CAP_BITS { HCLGE_CAP_FEC_B = 13, HCLGE_CAP_PAUSE_B = 14, HCLGE_CAP_RXD_ADV_LAYOUT_B = 15, + HCLGE_CAP_PORT_VLAN_BYPASS_B = 17, };
enum HCLGE_API_CAP_BITS { @@ -527,6 +529,8 @@ struct hclge_pf_res_cmd { #define HCLGE_CFG_SPEED_ABILITY_M GENMASK(7, 0) #define HCLGE_CFG_SPEED_ABILITY_EXT_S 10 #define HCLGE_CFG_SPEED_ABILITY_EXT_M GENMASK(15, 10) +#define HCLGE_CFG_VLAN_FLTR_CAP_S 8 +#define HCLGE_CFG_VLAN_FLTR_CAP_M GENMASK(9, 8) #define HCLGE_CFG_UMV_TBL_SPACE_S 16 #define HCLGE_CFG_UMV_TBL_SPACE_M GENMASK(31, 16) #define HCLGE_CFG_PF_RSS_SIZE_S 0 @@ -811,6 +815,14 @@ struct hclge_vlan_filter_vf_cfg_cmd { u8 vf_bitmap[HCLGE_MAX_VF_BYTES]; };
+#define HCLGE_INGRESS_BYPASS_B 0 +struct hclge_port_vlan_filter_bypass_cmd { + u8 bypass_state; + u8 rsv1[3]; + u8 vf_id; + u8 rsv2[19]; +}; + #define HCLGE_SWITCH_ANTI_SPOOF_B 0U #define HCLGE_SWITCH_ALW_LPBK_B 1U #define HCLGE_SWITCH_ALW_LCL_LPBK_B 2U diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 7c6b51f8d2b0..c6444d258328 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1334,6 +1334,10 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc) HCLGE_CFG_SPEED_ABILITY_EXT_S); cfg->speed_ability |= speed_ability_ext << SPEED_ABILITY_EXT_SHIFT;
+ cfg->vlan_fliter_cap = hnae3_get_field(__le32_to_cpu(req->param[1]), + HCLGE_CFG_VLAN_FLTR_CAP_M, + HCLGE_CFG_VLAN_FLTR_CAP_S); + cfg->umv_space = hnae3_get_field(__le32_to_cpu(req->param[1]), HCLGE_CFG_UMV_TBL_SPACE_M, HCLGE_CFG_UMV_TBL_SPACE_S); @@ -1513,6 +1517,7 @@ static void hclge_init_kdump_kernel_config(struct hclge_dev *hdev)
static int hclge_configure(struct hclge_dev *hdev) { + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); struct hclge_cfg cfg; unsigned int i; int ret; @@ -1534,6 +1539,8 @@ static int hclge_configure(struct hclge_dev *hdev) hdev->tc_max = cfg.tc_num; hdev->tm_info.hw_pfc_map = 0; hdev->wanted_umv_size = cfg.umv_space; + if (cfg.vlan_fliter_cap == HCLGE_VLAN_FLTR_CAN_MDF) + set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps);
if (hnae3_dev_fd_supported(hdev)) { hdev->fd_en = true; @@ -1843,6 +1850,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev) vport->mps = HCLGE_MAC_DEFAULT_FRAME; vport->port_base_vlan_cfg.state = HNAE3_PORT_BASE_VLAN_DISABLE; vport->rxvlan_cfg.rx_vlan_offload_en = true; + vport->req_vlan_fltr_en = true; INIT_LIST_HEAD(&vport->vlan_list); INIT_LIST_HEAD(&vport->uc_mac_list); INIT_LIST_HEAD(&vport->mc_mac_list); @@ -9381,6 +9389,28 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd); }
+static int hclge_set_port_vlan_filter_bypass(struct hclge_dev *hdev, u8 vf_id, + bool bypass_en) +{ + struct hclge_port_vlan_filter_bypass_cmd *req; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PORT_VLAN_BYPASS, false); + req = (struct hclge_port_vlan_filter_bypass_cmd *)desc.data; + req->vf_id = vf_id; + hnae3_set_bit(req->bypass_state, HCLGE_INGRESS_BYPASS_B, + bypass_en ? 1 : 0); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to set vport%u port vlan filter bypass state, ret = %d.\n", + vf_id, ret); + + return ret; +} + static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, u8 fe_type, bool filter_en, u8 vf_id) { @@ -9426,25 +9456,100 @@ static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, #define HCLGE_FILTER_FE_INGRESS (HCLGE_FILTER_FE_NIC_INGRESS_B \ | HCLGE_FILTER_FE_ROCE_INGRESS_B)
-static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) +static int hclge_set_vport_vlan_filter(struct hclge_vport *vport, bool enable) { - struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + struct hnae3_ae_dev *ae_dev = hdev->ae_dev; + int ret;
- if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { - hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, - HCLGE_FILTER_FE_EGRESS, enable, 0); - hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, - HCLGE_FILTER_FE_INGRESS, enable, 0); - } else { - hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, - HCLGE_FILTER_FE_EGRESS_V1_B, enable, - 0); + if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) + return hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, + HCLGE_FILTER_FE_EGRESS_V1_B, + enable, vport->vport_id); + + ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, + HCLGE_FILTER_FE_EGRESS, enable, + vport->vport_id); + if (ret) + return ret; + + if (test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, ae_dev->caps)) + ret = hclge_set_port_vlan_filter_bypass(hdev, vport->vport_id, + !enable); + else if (!vport->vport_id) + ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, + HCLGE_FILTER_FE_INGRESS, + enable, 0); + + return ret; +} + +static bool hclge_need_enable_vport_vlan_filter(struct hclge_vport *vport) +{ + struct hnae3_handle *handle = &vport->nic; + struct hclge_vport_vlan_cfg *vlan, *tmp; + struct hclge_dev *hdev = vport->back; + + if (vport->vport_id) { + if (vport->port_base_vlan_cfg.state != + HNAE3_PORT_BASE_VLAN_DISABLE) + return true; + + if (vport->vf_info.trusted && vport->vf_info.request_uc_en) + return false; + } else if (handle->netdev_flags & HNAE3_USER_UPE) { + return false; } - if (enable) - handle->netdev_flags |= HNAE3_VLAN_FLTR; - else - handle->netdev_flags &= ~HNAE3_VLAN_FLTR; + + if (!vport->req_vlan_fltr_en) + return false; + + /* compatible with former device, always enable vlan filter */ + if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, hdev->ae_dev->caps)) + return true; + + list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) + if (vlan->vlan_id != 0) + return true; + + return false; +} + +static int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, + bool request_en) +{ + struct hclge_dev *hdev = vport->back; + bool need_en; + int ret; + + mutex_lock(&hdev->vport_lock); + + vport->req_vlan_fltr_en = request_en; + + need_en = hclge_need_enable_vport_vlan_filter(vport); + if (need_en == vport->cur_vlan_fltr_en) { + mutex_unlock(&hdev->vport_lock); + return 0; + } + + ret = hclge_set_vport_vlan_filter(vport, need_en); + if (ret) { + mutex_unlock(&hdev->vport_lock); + return ret; + } + + vport->cur_vlan_fltr_en = need_en; + + mutex_unlock(&hdev->vport_lock); + + return 0; +} + +static int hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + + return hclge_enable_vport_vlan_filter(vport, enable); }
static int hclge_set_vf_vlan_filter_cmd(struct hclge_dev *hdev, u16 vfid, @@ -9838,6 +9943,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev) vport->vport_id); if (ret) return ret; + vport->cur_vlan_fltr_en = true; }
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, @@ -9853,8 +9959,6 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev) return ret; }
- handle->netdev_flags |= HNAE3_VLAN_FLTR; - hdev->vlan_type_cfg.rx_in_fst_vlan_type = HCLGE_DEF_VLAN_TYPE; hdev->vlan_type_cfg.rx_in_sec_vlan_type = HCLGE_DEF_VLAN_TYPE; hdev->vlan_type_cfg.rx_ot_fst_vlan_type = HCLGE_DEF_VLAN_TYPE; @@ -10077,6 +10181,14 @@ int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) return hclge_set_vlan_rx_offload_cfg(vport); }
+static void hclge_set_vport_vlan_fltr_change(struct hclge_vport *vport) +{ + struct hclge_dev *hdev = vport->back; + + if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, hdev->ae_dev->caps)) + set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, &vport->state); +} + static int hclge_update_vlan_filter_entries(struct hclge_vport *vport, u16 port_base_vlan_state, struct hclge_vlan_info *new_info, @@ -10185,6 +10297,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
vport->port_base_vlan_cfg.vlan_info = *vlan_info; + hclge_set_vport_vlan_fltr_change(vport);
return 0; } @@ -10328,9 +10441,37 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, */ set_bit(vlan_id, vport->vlan_del_fail_bmap); } + + hclge_set_vport_vlan_fltr_change(vport); + return ret; }
+static void hclge_sync_vlan_fltr_state(struct hclge_dev *hdev) +{ + struct hclge_vport *vport; + int ret; + u16 i; + + for (i = 0; i < hdev->num_alloc_vport; i++) { + vport = &hdev->vport[i]; + if (!test_and_clear_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, + &vport->state)) + continue; + + ret = hclge_enable_vport_vlan_filter(vport, + vport->req_vlan_fltr_en); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to sync vlan filter state for vport%u, ret = %d\n", + vport->vport_id, ret); + set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, + &vport->state); + return; + } + } +} + static void hclge_sync_vlan_filter(struct hclge_dev *hdev) { #define HCLGE_MAX_SYNC_COUNT 60 @@ -10353,6 +10494,7 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev)
clear_bit(vlan_id, vport->vlan_del_fail_bmap); hclge_rm_vport_vlan_table(vport, vlan_id, false); + hclge_set_vport_vlan_fltr_change(vport);
sync_cnt++; if (sync_cnt >= HCLGE_MAX_SYNC_COUNT) @@ -10362,6 +10504,8 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev) VLAN_N_VID); } } + + hclge_sync_vlan_fltr_state(hdev); }
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps) @@ -12452,8 +12596,8 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) if (!ret) { clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); - hclge_enable_vlan_filter(handle, - tmp_flags & HNAE3_VLAN_FLTR); + set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, + &vport->state); } }
@@ -12481,6 +12625,7 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) &vport->state); return; } + hclge_set_vport_vlan_fltr_change(vport); } }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index cd1e40152a67..eb0365231e4e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -321,6 +321,10 @@ enum hclge_fc_mode { HCLGE_FC_DEFAULT };
+enum hclge_vlan_fltr_cap { + HCLGE_VLAN_FLTR_DEF, + HCLGE_VLAN_FLTR_CAN_MDF, +}; enum hclge_link_fail_code { HCLGE_LF_NORMAL, HCLGE_LF_REF_CLOCK_LOST, @@ -351,6 +355,7 @@ struct hclge_tc_info {
struct hclge_cfg { u8 tc_num; + u8 vlan_fliter_cap; u16 tqp_desc_num; u16 rx_buf_len; u16 vf_rss_size_max; @@ -957,6 +962,7 @@ enum HCLGE_VPORT_STATE { HCLGE_VPORT_STATE_ALIVE, HCLGE_VPORT_STATE_MAC_TBL_CHANGE, HCLGE_VPORT_STATE_PROMISC_CHANGE, + HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, HCLGE_VPORT_STATE_MAX };
@@ -998,6 +1004,8 @@ struct hclge_vport { u32 bw_limit; /* VSI BW Limit (0 = disabled) */ u8 dwrr;
+ bool req_vlan_fltr_en; + bool cur_vlan_fltr_en; unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)]; struct hclge_port_base_vlan_config port_base_vlan_cfg; struct hclge_tx_vtag_cfg txvlan_cfg;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 32e6d104c6fe01713a039a98842e4d2f6bb505ec category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
There are some features of VF depend on PF, so it's necessary for VF to know whether PF supports. For compatibility, modify the mailbox HCLGE_MBX_GET_TCINFO, extend its function, use to get the basic information of PF, including mailbox api version and PF capabilities.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 9 ++++- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 3 ++ .../hisilicon/hns3/hns3pf/hclge_mbx.c | 19 +++++++---- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 33 +++++++++++-------- .../hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + 5 files changed, 45 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index a2c17af57fde..d75286202e7c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -20,7 +20,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_API_NEGOTIATE, /* (VF -> PF) negotiate API version */ HCLGE_MBX_GET_QINFO, /* (VF -> PF) get queue config */ HCLGE_MBX_GET_QDEPTH, /* (VF -> PF) get queue depth */ - HCLGE_MBX_GET_TCINFO, /* (VF -> PF) get TC config */ + HCLGE_MBX_GET_BASIC_INFO, /* (VF -> PF) get basic info */ HCLGE_MBX_GET_RETA, /* (VF -> PF) get RETA */ HCLGE_MBX_GET_RSS_KEY, /* (VF -> PF) get RSS key */ HCLGE_MBX_GET_MAC_ADDR, /* (VF -> PF) get MAC addr */ @@ -85,6 +85,13 @@ struct hclge_ring_chain_param { u8 int_gl_index; };
+struct hclge_basic_info { + u8 hw_tc_map; + u8 rsv; + u16 mbx_api_version; + u32 pf_caps; +}; + struct hclgevf_mbx_resp_status { struct mutex mbx_mutex; /* protects against contending sync cmd resp */ u32 origin_mbx_msg; diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 5aeda231a683..3b7ae4015c9e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -146,6 +146,9 @@ enum HNAE3_DEV_CAP_BITS { #define hnae3_ae_dev_rxd_adv_layout_supported(ae_dev) \ test_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, (ae_dev)->caps)
+enum HNAE3_PF_CAP_BITS { + HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0, +}; #define ring_ptr_move_fw(ring, p) \ ((ring)->p = ((ring)->p + 1) % (ring)->desc_num) #define ring_ptr_move_bw(ring, p) \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 54eee94df47a..59951949ec2d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -384,16 +384,23 @@ static int hclge_set_vf_alive(struct hclge_vport *vport, return ret; }
-static void hclge_get_vf_tcinfo(struct hclge_vport *vport, - struct hclge_respond_to_vf_msg *resp_msg) +static void hclge_get_basic_info(struct hclge_vport *vport, + struct hclge_respond_to_vf_msg *resp_msg) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; + struct hnae3_ae_dev *ae_dev = vport->back->ae_dev; + struct hclge_basic_info *basic_info; unsigned int i;
+ basic_info = (struct hclge_basic_info *)resp_msg->data; for (i = 0; i < kinfo->tc_info.num_tc; i++) - resp_msg->data[0] |= BIT(i); + basic_info->hw_tc_map |= BIT(i);
- resp_msg->len = sizeof(u8); + if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) + hnae3_set_bit(basic_info->pf_caps, + HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B, 1); + + resp_msg->len = HCLGE_MBX_MAX_RESP_DATA_SIZE; }
static void hclge_get_vf_queue_info(struct hclge_vport *vport, @@ -752,8 +759,8 @@ void hclge_mbx_handler(struct hclge_dev *hdev) case HCLGE_MBX_GET_QDEPTH: hclge_get_vf_queue_depth(vport, &resp_msg); break; - case HCLGE_MBX_GET_TCINFO: - hclge_get_vf_tcinfo(vport, &resp_msg); + case HCLGE_MBX_GET_BASIC_INFO: + hclge_get_basic_info(vport, &resp_msg); break; case HCLGE_MBX_GET_LINK_STATUS: ret = hclge_push_vf_link_status(vport); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 7bef6b24e610..7c101455f1e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -243,23 +243,31 @@ static void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code, } }
-static int hclgevf_get_tc_info(struct hclgevf_dev *hdev) +static int hclgevf_get_basic_info(struct hclgevf_dev *hdev) { + struct hnae3_ae_dev *ae_dev = hdev->ae_dev; + u8 resp_msg[HCLGE_MBX_MAX_RESP_DATA_SIZE]; + struct hclge_basic_info *basic_info; struct hclge_vf_to_pf_msg send_msg; - u8 resp_msg; + unsigned long caps; int status;
- hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_TCINFO, 0); - status = hclgevf_send_mbx_msg(hdev, &send_msg, true, &resp_msg, + hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_BASIC_INFO, 0); + status = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg, sizeof(resp_msg)); if (status) { dev_err(&hdev->pdev->dev, - "VF request to get TC info from PF failed %d", - status); + "failed to get basic info from pf, ret = %d", status); return status; }
- hdev->hw_tc_map = resp_msg; + basic_info = (struct hclge_basic_info *)resp_msg; + + hdev->hw_tc_map = basic_info->hw_tc_map; + hdev->mbx_api_version = basic_info->mbx_api_version; + caps = basic_info->pf_caps; + if (test_bit(HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B, &caps)) + set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps);
return 0; } @@ -2466,6 +2474,10 @@ static int hclgevf_configure(struct hclgevf_dev *hdev) { int ret;
+ ret = hclgevf_get_basic_info(hdev); + if (ret) + return ret; + /* get current port based vlan state from PF */ ret = hclgevf_get_port_base_vlan_filter_state(hdev); if (ret) @@ -2481,12 +2493,7 @@ static int hclgevf_configure(struct hclgevf_dev *hdev) if (ret) return ret;
- ret = hclgevf_get_pf_media_type(hdev); - if (ret) - return ret; - - /* get tc configuration from PF */ - return hclgevf_get_tc_info(hdev); + return hclgevf_get_pf_media_type(hdev); }
static int hclgevf_alloc_hdev(struct hnae3_ae_dev *ae_dev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index b146d04526de..d7d02848d674 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -285,6 +285,7 @@ struct hclgevf_dev { struct semaphore reset_sem; /* protect reset process */
u32 fw_version; + u16 mbx_api_version; u16 num_tqps; /* num task queue pairs of this VF */
u16 alloc_rss_size; /* allocated RSS task queue */
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit fa6a262a255003ebb1f514fffd3399f3946d4fc9 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Previously, there is hardware limitation for VF to modify the VLAN filter state, and the VLAN filter state is default enabled. Now the limitation has been removed in some device, so add capability flag to check whether the device supports modify VLAN filter state. If flag on, user will be able to modify the VLAN filter state by ethtool -K. VF needs to send mailbox to request the PF to modify the VLAN filter state for it.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 1 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +-- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 + .../ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 ++ .../hisilicon/hns3/hns3vf/hclgevf_main.c | 17 +++++++++++++++++ 5 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index d75286202e7c..0a6cda309b24 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -69,6 +69,7 @@ enum hclge_mbx_vlan_cfg_subcode { HCLGE_MBX_VLAN_RX_OFF_CFG, /* set rx side vlan offload */ HCLGE_MBX_PORT_BASE_VLAN_CFG, /* set port based vlan configuration */ HCLGE_MBX_GET_PORT_BASE_VLAN_STATE, /* get port based vlan state */ + HCLGE_MBX_ENABLE_VLAN_FILTER, };
enum hclge_mbx_tbl_cfg_subcode { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c6444d258328..35aa4ac4b09b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -9515,8 +9515,7 @@ static bool hclge_need_enable_vport_vlan_filter(struct hclge_vport *vport) return false; }
-static int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, - bool request_en) +int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en) { struct hclge_dev *hdev = vport->back; bool need_en; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index eb0365231e4e..bb778433f63d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1107,4 +1107,5 @@ void hclge_report_hw_error(struct hclge_dev *hdev, void hclge_inform_vf_promisc_info(struct hclge_vport *vport); int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); int hclge_push_vf_link_status(struct hclge_vport *vport); +int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 59951949ec2d..e10a2c36b706 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -365,6 +365,8 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport, vport->port_base_vlan_cfg.state; resp_msg->len = sizeof(u8); return 0; + case HCLGE_MBX_ENABLE_VLAN_FILTER: + return hclge_enable_vport_vlan_filter(vport, msg_cmd->enable); default: return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 7c101455f1e4..f84b3a135c06 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1650,6 +1650,22 @@ static void hclgevf_uninit_mac_list(struct hclgevf_dev *hdev) spin_unlock_bh(&hdev->mac_table.mac_list_lock); }
+static int hclgevf_enable_vlan_filter(struct hnae3_handle *handle, bool enable) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + struct hnae3_ae_dev *ae_dev = hdev->ae_dev; + struct hclge_vf_to_pf_msg send_msg; + + if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) + return -EOPNOTSUPP; + + hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN, + HCLGE_MBX_ENABLE_VLAN_FILTER); + send_msg.data[0] = enable ? 1 : 0; + + return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0); +} + static int hclgevf_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, u16 vlan_id, bool is_kill) @@ -3808,6 +3824,7 @@ static const struct hnae3_ae_ops hclgevf_ops = { .get_tc_size = hclgevf_get_tc_size, .get_fw_version = hclgevf_get_fw_version, .set_vlan_filter = hclgevf_set_vlan_filter, + .enable_vlan_filter = hclgevf_enable_vlan_filter, .enable_hw_strip_rxvtag = hclgevf_en_hw_strip_rxvtag, .reset_event = hclgevf_reset_event, .set_default_reset_request = hclgevf_set_def_reset_request,
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 0ca821da86a5ec24eb2ece24fe87e5bf518c5939 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Add debugfs support for vlan configuraion. create a single file "vlan_config" for it, and query it by command "cat vlan_config", return the result to userspace.
The new display style is below: $ cat vlan_config I_PORT_VLAN_FILTER: on E_PORT_VLAN_FILTER: off FUNC_ID I_VF_VLAN_FILTER E_VF_VLAN_FILTER PORT_VLAN_FILTER_BYPASS pf off on off vf0 off on off FUNC_ID PVID ACCEPT_TAG1 ACCEPT_TAG2 ACCEPT_UNTAG1 ACCEPT_UNTAG2 pf 0 on on on on vf0 0 on on on on
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Jakub Kicinski kuba@kernel.org Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 7 + .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 283 ++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_debugfs.h | 19 ++ .../hisilicon/hns3/hns3pf/hclge_main.c | 12 - .../hisilicon/hns3/hns3pf/hclge_main.h | 12 + 6 files changed, 322 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 3b7ae4015c9e..990c60c97d26 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -287,6 +287,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_REG_TQP, HNAE3_DBG_CMD_REG_MAC, HNAE3_DBG_CMD_REG_DCB, + HNAE3_DBG_CMD_VLAN_CONFIG, HNAE3_DBG_CMD_QUEUE_MAP, HNAE3_DBG_CMD_RX_QUEUE_INFO, HNAE3_DBG_CMD_TX_QUEUE_INFO, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 3feba43586e0..cf1efd2f4a0f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -309,6 +309,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "vlan_config", + .cmd = HNAE3_DBG_CMD_VLAN_CONFIG, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 0b7c6838d905..0d433a5ff807 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1894,6 +1894,285 @@ static void hclge_dbg_dump_mac_list(struct hclge_dev *hdev, char *buf, int len, } }
+static int hclge_get_vlan_rx_offload_cfg(struct hclge_dev *hdev, u8 vf_id, + struct hclge_dbg_vlan_cfg *vlan_cfg) +{ + struct hclge_vport_vtag_rx_cfg_cmd *req; + struct hclge_desc desc; + u16 bmap_index; + u8 rx_cfg; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_PORT_RX_CFG, true); + + req = (struct hclge_vport_vtag_rx_cfg_cmd *)desc.data; + req->vf_offset = vf_id / HCLGE_VF_NUM_PER_CMD; + bmap_index = vf_id % HCLGE_VF_NUM_PER_CMD / HCLGE_VF_NUM_PER_BYTE; + req->vf_bitmap[bmap_index] = 1U << (vf_id % HCLGE_VF_NUM_PER_BYTE); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get vport%u rxvlan cfg, ret = %d\n", + vf_id, ret); + return ret; + } + + rx_cfg = req->vport_vlan_cfg; + vlan_cfg->strip_tag1 = hnae3_get_bit(rx_cfg, HCLGE_REM_TAG1_EN_B); + vlan_cfg->strip_tag2 = hnae3_get_bit(rx_cfg, HCLGE_REM_TAG2_EN_B); + vlan_cfg->drop_tag1 = hnae3_get_bit(rx_cfg, HCLGE_DISCARD_TAG1_EN_B); + vlan_cfg->drop_tag2 = hnae3_get_bit(rx_cfg, HCLGE_DISCARD_TAG2_EN_B); + vlan_cfg->pri_only1 = hnae3_get_bit(rx_cfg, HCLGE_SHOW_TAG1_EN_B); + vlan_cfg->pri_only2 = hnae3_get_bit(rx_cfg, HCLGE_SHOW_TAG2_EN_B); + + return 0; +} + +static int hclge_get_vlan_tx_offload_cfg(struct hclge_dev *hdev, u8 vf_id, + struct hclge_dbg_vlan_cfg *vlan_cfg) +{ + struct hclge_vport_vtag_tx_cfg_cmd *req; + struct hclge_desc desc; + u16 bmap_index; + u8 tx_cfg; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_PORT_TX_CFG, true); + req = (struct hclge_vport_vtag_tx_cfg_cmd *)desc.data; + req->vf_offset = vf_id / HCLGE_VF_NUM_PER_CMD; + bmap_index = vf_id % HCLGE_VF_NUM_PER_CMD / HCLGE_VF_NUM_PER_BYTE; + req->vf_bitmap[bmap_index] = 1U << (vf_id % HCLGE_VF_NUM_PER_BYTE); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get vport%u txvlan cfg, ret = %d\n", + vf_id, ret); + return ret; + } + + tx_cfg = req->vport_vlan_cfg; + vlan_cfg->pvid = le16_to_cpu(req->def_vlan_tag1); + + vlan_cfg->accept_tag1 = hnae3_get_bit(tx_cfg, HCLGE_ACCEPT_TAG1_B); + vlan_cfg->accept_tag2 = hnae3_get_bit(tx_cfg, HCLGE_ACCEPT_TAG2_B); + vlan_cfg->accept_untag1 = hnae3_get_bit(tx_cfg, HCLGE_ACCEPT_UNTAG1_B); + vlan_cfg->accept_untag2 = hnae3_get_bit(tx_cfg, HCLGE_ACCEPT_UNTAG2_B); + vlan_cfg->insert_tag1 = hnae3_get_bit(tx_cfg, HCLGE_PORT_INS_TAG1_EN_B); + vlan_cfg->insert_tag2 = hnae3_get_bit(tx_cfg, HCLGE_PORT_INS_TAG2_EN_B); + vlan_cfg->shift_tag = hnae3_get_bit(tx_cfg, HCLGE_TAG_SHIFT_MODE_EN_B); + + return 0; +} + +static int hclge_get_vlan_filter_config_cmd(struct hclge_dev *hdev, + u8 vlan_type, u8 vf_id, + struct hclge_desc *desc) +{ + struct hclge_vlan_filter_ctrl_cmd *req; + int ret; + + hclge_cmd_setup_basic_desc(desc, HCLGE_OPC_VLAN_FILTER_CTRL, true); + req = (struct hclge_vlan_filter_ctrl_cmd *)desc->data; + req->vlan_type = vlan_type; + req->vf_id = vf_id; + + ret = hclge_cmd_send(&hdev->hw, desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to get vport%u vlan filter config, ret = %d.\n", + vf_id, ret); + + return ret; +} + +static int hclge_get_vlan_filter_state(struct hclge_dev *hdev, u8 vlan_type, + u8 vf_id, u8 *vlan_fe) +{ + struct hclge_vlan_filter_ctrl_cmd *req; + struct hclge_desc desc; + int ret; + + ret = hclge_get_vlan_filter_config_cmd(hdev, vlan_type, vf_id, &desc); + if (ret) + return ret; + + req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data; + *vlan_fe = req->vlan_fe; + + return 0; +} + +static int hclge_get_port_vlan_filter_bypass_state(struct hclge_dev *hdev, + u8 vf_id, u8 *bypass_en) +{ + struct hclge_port_vlan_filter_bypass_cmd *req; + struct hclge_desc desc; + int ret; + + if (!test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, hdev->ae_dev->caps)) + return 0; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PORT_VLAN_BYPASS, true); + req = (struct hclge_port_vlan_filter_bypass_cmd *)desc.data; + req->vf_id = vf_id; + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get vport%u port vlan filter bypass state, ret = %d.\n", + vf_id, ret); + return ret; + } + + *bypass_en = hnae3_get_bit(req->bypass_state, HCLGE_INGRESS_BYPASS_B); + + return 0; +} + +static const struct hclge_dbg_item vlan_filter_items[] = { + { "FUNC_ID", 2 }, + { "I_VF_VLAN_FILTER", 2 }, + { "E_VF_VLAN_FILTER", 2 }, + { "PORT_VLAN_FILTER_BYPASS", 0 } +}; + +static const struct hclge_dbg_item vlan_offload_items[] = { + { "FUNC_ID", 2 }, + { "PVID", 4 }, + { "ACCEPT_TAG1", 2 }, + { "ACCEPT_TAG2", 2 }, + { "ACCEPT_UNTAG1", 2 }, + { "ACCEPT_UNTAG2", 2 }, + { "INSERT_TAG1", 2 }, + { "INSERT_TAG2", 2 }, + { "SHIFT_TAG", 2 }, + { "STRIP_TAG1", 2 }, + { "STRIP_TAG2", 2 }, + { "DROP_TAG1", 2 }, + { "DROP_TAG2", 2 }, + { "PRI_ONLY_TAG1", 2 }, + { "PRI_ONLY_TAG2", 0 } +}; + +static int hclge_dbg_dump_vlan_filter_config(struct hclge_dev *hdev, char *buf, + int len, int *pos) +{ + char content[HCLGE_DBG_VLAN_FLTR_INFO_LEN], str_id[HCLGE_DBG_ID_LEN]; + const char *result[ARRAY_SIZE(vlan_filter_items)]; + u8 i, j, vlan_fe, bypass, ingress, egress; + u8 func_num = pci_num_vf(hdev->pdev) + 1; /* pf and enabled vf num */ + int ret; + + ret = hclge_get_vlan_filter_state(hdev, HCLGE_FILTER_TYPE_PORT, 0, + &vlan_fe); + if (ret) + return ret; + ingress = vlan_fe & HCLGE_FILTER_FE_NIC_INGRESS_B; + egress = vlan_fe & HCLGE_FILTER_FE_NIC_EGRESS_B ? 1 : 0; + + *pos += scnprintf(buf, len, "I_PORT_VLAN_FILTER: %s\n", + state_str[ingress]); + *pos += scnprintf(buf + *pos, len - *pos, "E_PORT_VLAN_FILTER: %s\n", + state_str[egress]); + + hclge_dbg_fill_content(content, sizeof(content), vlan_filter_items, + NULL, ARRAY_SIZE(vlan_filter_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + + for (i = 0; i < func_num; i++) { + ret = hclge_get_vlan_filter_state(hdev, HCLGE_FILTER_TYPE_VF, i, + &vlan_fe); + if (ret) + return ret; + + ingress = vlan_fe & HCLGE_FILTER_FE_NIC_INGRESS_B; + egress = vlan_fe & HCLGE_FILTER_FE_NIC_EGRESS_B ? 1 : 0; + ret = hclge_get_port_vlan_filter_bypass_state(hdev, i, &bypass); + if (ret) + return ret; + j = 0; + result[j++] = hclge_dbg_get_func_id_str(str_id, i); + result[j++] = state_str[ingress]; + result[j++] = state_str[egress]; + result[j++] = + test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, + hdev->ae_dev->caps) ? state_str[bypass] : "NA"; + hclge_dbg_fill_content(content, sizeof(content), + vlan_filter_items, result, + ARRAY_SIZE(vlan_filter_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + } + *pos += scnprintf(buf + *pos, len - *pos, "\n"); + + return 0; +} + +static int hclge_dbg_dump_vlan_offload_config(struct hclge_dev *hdev, char *buf, + int len, int *pos) +{ + char str_id[HCLGE_DBG_ID_LEN], str_pvid[HCLGE_DBG_ID_LEN]; + const char *result[ARRAY_SIZE(vlan_offload_items)]; + char content[HCLGE_DBG_VLAN_OFFLOAD_INFO_LEN]; + u8 func_num = pci_num_vf(hdev->pdev) + 1; /* pf and enabled vf num */ + struct hclge_dbg_vlan_cfg vlan_cfg; + int ret; + u8 i, j; + + hclge_dbg_fill_content(content, sizeof(content), vlan_offload_items, + NULL, ARRAY_SIZE(vlan_offload_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + + for (i = 0; i < func_num; i++) { + ret = hclge_get_vlan_tx_offload_cfg(hdev, i, &vlan_cfg); + if (ret) + return ret; + + ret = hclge_get_vlan_rx_offload_cfg(hdev, i, &vlan_cfg); + if (ret) + return ret; + + sprintf(str_pvid, "%u", vlan_cfg.pvid); + j = 0; + result[j++] = hclge_dbg_get_func_id_str(str_id, i); + result[j++] = str_pvid; + result[j++] = state_str[vlan_cfg.accept_tag1]; + result[j++] = state_str[vlan_cfg.accept_tag2]; + result[j++] = state_str[vlan_cfg.accept_untag1]; + result[j++] = state_str[vlan_cfg.accept_untag2]; + result[j++] = state_str[vlan_cfg.insert_tag1]; + result[j++] = state_str[vlan_cfg.insert_tag2]; + result[j++] = state_str[vlan_cfg.shift_tag]; + result[j++] = state_str[vlan_cfg.strip_tag1]; + result[j++] = state_str[vlan_cfg.strip_tag2]; + result[j++] = state_str[vlan_cfg.drop_tag1]; + result[j++] = state_str[vlan_cfg.drop_tag2]; + result[j++] = state_str[vlan_cfg.pri_only1]; + result[j++] = state_str[vlan_cfg.pri_only2]; + + hclge_dbg_fill_content(content, sizeof(content), + vlan_offload_items, result, + ARRAY_SIZE(vlan_offload_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + } + + return 0; +} + +static int hclge_dbg_dump_vlan_config(struct hclge_dev *hdev, char *buf, + int len) +{ + int pos = 0; + int ret; + + ret = hclge_dbg_dump_vlan_filter_config(hdev, buf, len, &pos); + if (ret) + return ret; + + return hclge_dbg_dump_vlan_offload_config(hdev, buf, len, &pos); +} + static int hclge_dbg_dump_mac_uc(struct hclge_dev *hdev, char *buf, int len) { hclge_dbg_dump_mac_list(hdev, buf, len, true); @@ -2037,6 +2316,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_SERV_INFO, .dbg_dump = hclge_dbg_dump_serv_info, }, + { + .cmd = HNAE3_DBG_CMD_VLAN_CONFIG, + .dbg_dump = hclge_dbg_dump_vlan_config, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index 642752e65a7c..c526591a7240 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -735,6 +735,8 @@ static const struct hclge_dbg_dfx_message hclge_dbg_tqp_reg[] = { };
#define HCLGE_DBG_INFO_LEN 256 +#define HCLGE_DBG_VLAN_FLTR_INFO_LEN 256 +#define HCLGE_DBG_VLAN_OFFLOAD_INFO_LEN 512 #define HCLGE_DBG_ID_LEN 16 #define HCLGE_DBG_ITEM_NAME_LEN 32 #define HCLGE_DBG_DATA_STR_LEN 32 @@ -747,4 +749,21 @@ struct hclge_dbg_item { u16 interval; /* blank numbers after the item */ };
+struct hclge_dbg_vlan_cfg { + u16 pvid; + u8 accept_tag1; + u8 accept_tag2; + u8 accept_untag1; + u8 accept_untag2; + u8 insert_tag1; + u8 insert_tag2; + u8 shift_tag; + u8 strip_tag1; + u8 strip_tag2; + u8 drop_tag1; + u8 drop_tag2; + u8 pri_only1; + u8 pri_only2; +}; + #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 35aa4ac4b09b..6ecc106af334 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -9444,18 +9444,6 @@ static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, return ret; }
-#define HCLGE_FILTER_TYPE_VF 0 -#define HCLGE_FILTER_TYPE_PORT 1 -#define HCLGE_FILTER_FE_EGRESS_V1_B BIT(0) -#define HCLGE_FILTER_FE_NIC_INGRESS_B BIT(0) -#define HCLGE_FILTER_FE_NIC_EGRESS_B BIT(1) -#define HCLGE_FILTER_FE_ROCE_INGRESS_B BIT(2) -#define HCLGE_FILTER_FE_ROCE_EGRESS_B BIT(3) -#define HCLGE_FILTER_FE_EGRESS (HCLGE_FILTER_FE_NIC_EGRESS_B \ - | HCLGE_FILTER_FE_ROCE_EGRESS_B) -#define HCLGE_FILTER_FE_INGRESS (HCLGE_FILTER_FE_NIC_INGRESS_B \ - | HCLGE_FILTER_FE_ROCE_INGRESS_B) - static int hclge_set_vport_vlan_filter(struct hclge_vport *vport, bool enable) { struct hclge_dev *hdev = vport->back; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index bb778433f63d..7595f841aaac 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -321,6 +321,18 @@ enum hclge_fc_mode { HCLGE_FC_DEFAULT };
+#define HCLGE_FILTER_TYPE_VF 0 +#define HCLGE_FILTER_TYPE_PORT 1 +#define HCLGE_FILTER_FE_EGRESS_V1_B BIT(0) +#define HCLGE_FILTER_FE_NIC_INGRESS_B BIT(0) +#define HCLGE_FILTER_FE_NIC_EGRESS_B BIT(1) +#define HCLGE_FILTER_FE_ROCE_INGRESS_B BIT(2) +#define HCLGE_FILTER_FE_ROCE_EGRESS_B BIT(3) +#define HCLGE_FILTER_FE_EGRESS (HCLGE_FILTER_FE_NIC_EGRESS_B \ + | HCLGE_FILTER_FE_ROCE_EGRESS_B) +#define HCLGE_FILTER_FE_INGRESS (HCLGE_FILTER_FE_NIC_INGRESS_B \ + | HCLGE_FILTER_FE_ROCE_INGRESS_B) + enum hclge_vlan_fltr_cap { HCLGE_VLAN_FLTR_DEF, HCLGE_VLAN_FLTR_CAN_MDF,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit d991452dd7900cf152ffb43db3b1d385e1a01579 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Error handling and recovery logic are intertwined. Error handling (i.e. error identification, clearing error sources and initiation of recovery) is done in context of reset task. If certain hardware errors get delivered during driver init time, which can cause driver init/loading to fail.
Introduce a separate error handling task to ensure below:
1. Reset logic remains independent of the error handling logic. 2. Add the hclge_errhand_task_schedule to schedule error recovery tasks, This will ensure that common misellaneous MSI-X interrupt are re-enabled quickly.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Salil Mehta salil.mehta@huawei.com Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_err.c | 4 +- .../hisilicon/hns3/hns3pf/hclge_main.c | 38 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + 3 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 8223d699cd94..f125aa425872 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1940,8 +1940,8 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev,
if (!test_bit(HCLGE_STATE_SERVICE_INITED, &hdev->state)) { dev_err(dev, - "Can't handle - MSIx error reported during dev init\n"); - return 0; + "failed to handle msix error during dev init\n"); + return -EAGAIN; }
return hclge_handle_all_hw_msix_error(hdev, reset_requests); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6ecc106af334..8a431e124adb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2843,6 +2843,14 @@ static void hclge_reset_task_schedule(struct hclge_dev *hdev) hclge_wq, &hdev->service_task, 0); }
+static void hclge_errhand_task_schedule(struct hclge_dev *hdev) +{ + if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) && + !test_and_set_bit(HCLGE_STATE_ERR_SERVICE_SCHED, &hdev->state)) + mod_delayed_work_on(cpumask_first(&hdev->affinity_mask), + hclge_wq, &hdev->service_task, 0); +} + void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time) { if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) && @@ -4264,6 +4272,36 @@ static void hclge_reset_subtask(struct hclge_dev *hdev) hdev->reset_type = HNAE3_NONE_RESET; }
+static void hclge_misc_err_recovery(struct hclge_dev *hdev) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + struct device *dev = &hdev->pdev->dev; + u32 msix_sts_reg; + + msix_sts_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS); + + if (msix_sts_reg & HCLGE_VECTOR0_REG_MSIX_MASK) { + if (hclge_handle_hw_msix_error(hdev, + &hdev->default_reset_request)) + dev_info(dev, "received msix interrupt 0x%x\n", + msix_sts_reg); + + if (hdev->default_reset_request) + if (ae_dev->ops->reset_event) + ae_dev->ops->reset_event(hdev->pdev, NULL); + } + + hclge_enable_vector(&hdev->misc_vector, true); +} + +static void hclge_errhand_service_task(struct hclge_dev *hdev) +{ + if (!test_and_clear_bit(HCLGE_STATE_ERR_SERVICE_SCHED, &hdev->state)) + return; + + hclge_misc_err_recovery(hdev); +} + static void hclge_reset_service_task(struct hclge_dev *hdev) { if (!test_and_clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state)) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 7595f841aaac..9b8abb5d7a8e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -221,6 +221,7 @@ enum HCLGE_DEV_STATE { HCLGE_STATE_RST_HANDLING, HCLGE_STATE_MBX_SERVICE_SCHED, HCLGE_STATE_MBX_HANDLING, + HCLGE_STATE_ERR_SERVICE_SCHED, HCLGE_STATE_STATISTICS_UPDATING, HCLGE_STATE_CMD_DISABLE, HCLGE_STATE_LINK_UPDATING,
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit aff399a638da7e56680cdf6fa7544b67e0373a4e category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Error handling & recovery is done in context of reset task which gets scheduled from misc interrupt handler in existing code. But since error handling has been moved to new task, it should get scheduled instead of the reset task from the interrupt handler.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Salil Mehta salil.mehta@huawei.com Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_main.c | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 8a431e124adb..4b1aa5c45852 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3402,18 +3402,8 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) /* vector 0 interrupt is shared with reset and mailbox source events.*/ switch (event_cause) { case HCLGE_VECTOR0_EVENT_ERR: - /* we do not know what type of reset is required now. This could - * only be decided after we fetch the type of errors which - * caused this event. Therefore, we will do below for now: - * 1. Assert HNAE3_UNKNOWN_RESET type of reset. This means we - * have defered type of reset to be used. - * 2. Schedule the reset service task. - * 3. When service task receives HNAE3_UNKNOWN_RESET type it - * will fetch the correct type of reset. This would be done - * by first decoding the types of errors. - */ - set_bit(HNAE3_UNKNOWN_RESET, &hdev->reset_request); - fallthrough; + hclge_errhand_task_schedule(hdev); + break; case HCLGE_VECTOR0_EVENT_RST: hclge_reset_task_schedule(hdev); break; @@ -4385,14 +4375,16 @@ static void hclge_service_task(struct work_struct *work) struct hclge_dev *hdev = container_of(work, struct hclge_dev, service_task.work);
+ hclge_errhand_service_task(hdev); hclge_reset_service_task(hdev); hclge_mailbox_service_task(hdev); hclge_periodic_service_task(hdev);
- /* Handle reset and mbx again in case periodical task delays the - * handling by calling hclge_task_schedule() in + /* Handle error recovery, reset and mbx again in case periodical task + * delays the handling by calling hclge_task_schedule() in * hclge_periodic_service_task(). */ + hclge_errhand_service_task(hdev); hclge_reset_service_task(hdev); hclge_mailbox_service_task(hdev); }
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit e0fe0a38371b6d2d669e231c1fd68ce620dfa6b2 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Earlier patches have decoupled the MSI-X conveyed error handling and recovery logic. This earlier concept code is no longer required.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Salil Mehta salil.mehta@huawei.com Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 - .../hisilicon/hns3/hns3pf/hclge_main.c | 22 ------------------- 2 files changed, 23 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 990c60c97d26..bf10652f07ee 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -242,7 +242,6 @@ enum hnae3_reset_type { HNAE3_FUNC_RESET, HNAE3_GLOBAL_RESET, HNAE3_IMP_RESET, - HNAE3_UNKNOWN_RESET, HNAE3_NONE_RESET, HNAE3_MAX_RESET, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 4b1aa5c45852..45102681bd2a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3792,28 +3792,6 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hnae3_ae_dev *ae_dev, enum hnae3_reset_type rst_level = HNAE3_NONE_RESET; struct hclge_dev *hdev = ae_dev->priv;
- /* first, resolve any unknown reset type to the known type(s) */ - if (test_bit(HNAE3_UNKNOWN_RESET, addr)) { - u32 msix_sts_reg = hclge_read_dev(&hdev->hw, - HCLGE_MISC_VECTOR_INT_STS); - /* we will intentionally ignore any errors from this function - * as we will end up in *some* reset request in any case - */ - if (hclge_handle_hw_msix_error(hdev, addr)) - dev_info(&hdev->pdev->dev, "received msix interrupt 0x%x\n", - msix_sts_reg); - - clear_bit(HNAE3_UNKNOWN_RESET, addr); - /* We defered the clearing of the error event which caused - * interrupt since it was not posssible to do that in - * interrupt context (and this is the reason we introduced - * new UNKNOWN reset type). Now, the errors have been - * handled and cleared in hardware we can safely enable - * interrupts. This is an exception to the norm. - */ - hclge_enable_vector(&hdev->misc_vector, true); - } - /* return the highest priority reset level amongst all */ if (test_bit(HNAE3_IMP_RESET, addr)) { rst_level = HNAE3_IMP_RESET;
From: Yufeng Mo moyufeng@huawei.com
mainline inclusion from mainline-master commit 17f59244029bf9c0673725efdd0386ed95e127a7 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently, hardware errors can be reported through AER or MSI-X mode. However, the AER mode is intended to handle only bus errors, but not hardware errors. On the other hand, virtual machines cannot handle AER errors. When an AER error is reported, virtual machines will be suspended. So add support for handling all these hardware errors through MSI-X mode which depends on a newer version of firmware, and reserve the handler of the AER mode for compatibility.
Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_err.c | 16 +++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 47 ++++++++++--------- .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + 3 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index f125aa425872..540dd15d7771 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1611,11 +1611,27 @@ static const struct hclge_hw_blk hw_blk[] = { { /* sentinel */ } };
+static void hclge_config_all_msix_error(struct hclge_dev *hdev, bool enable) +{ + u32 reg_val; + + reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG); + + if (enable) + reg_val |= BIT(HCLGE_VECTOR0_ALL_MSIX_ERR_B); + else + reg_val &= ~BIT(HCLGE_VECTOR0_ALL_MSIX_ERR_B); + + hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, reg_val); +} + int hclge_config_nic_hw_error(struct hclge_dev *hdev, bool state) { const struct hclge_hw_blk *module = hw_blk; int ret = 0;
+ hclge_config_all_msix_error(hdev, state); + while (module->name) { if (module->config_err_int) { ret = module->config_err_int(hdev, state); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 45102681bd2a..d5be3bc50b5c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3307,11 +3307,13 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) { - u32 cmdq_src_reg, msix_src_reg; + u32 cmdq_src_reg, msix_src_reg, hw_err_src_reg;
/* fetch the events from their corresponding regs */ cmdq_src_reg = hclge_read_dev(&hdev->hw, HCLGE_VECTOR0_CMDQ_SRC_REG); msix_src_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS); + hw_err_src_reg = hclge_read_dev(&hdev->hw, + HCLGE_RAS_PF_OTHER_INT_STS_REG);
/* Assumption: If by any chance reset and mailbox events are reported * together then we will only process reset event in this go and will @@ -3339,11 +3341,11 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) return HCLGE_VECTOR0_EVENT_RST; }
- /* check for vector0 msix event source */ - if (msix_src_reg & HCLGE_VECTOR0_REG_MSIX_MASK) { - *clearval = msix_src_reg; + /* check for vector0 msix event and hardware error event source */ + if (msix_src_reg & HCLGE_VECTOR0_REG_MSIX_MASK || + hw_err_src_reg & HCLGE_RAS_REG_NFE_MASK || + hw_err_src_reg & HCLGE_RAS_REG_ROCEE_ERR_MASK) return HCLGE_VECTOR0_EVENT_ERR; - }
/* check for vector0 mailbox(=CMDQ RX) event source */ if (BIT(HCLGE_VECTOR0_RX_CMDQ_INT_B) & cmdq_src_reg) { @@ -3354,9 +3356,8 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
/* print other vector0 event source */ dev_info(&hdev->pdev->dev, - "CMDQ INT status:0x%x, other INT status:0x%x\n", - cmdq_src_reg, msix_src_reg); - *clearval = msix_src_reg; + "INT status: CMDQ(%#x) HW errors(%#x) other(%#x)\n", + cmdq_src_reg, hw_err_src_reg, msix_src_reg);
return HCLGE_VECTOR0_EVENT_OTHER; } @@ -3427,15 +3428,10 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data)
hclge_clear_event_cause(hdev, event_cause, clearval);
- /* Enable interrupt if it is not cause by reset. And when - * clearval equal to 0, it means interrupt status may be - * cleared by hardware before driver reads status register. - * For this case, vector0 interrupt also should be enabled. - */ - if (!clearval || - event_cause == HCLGE_VECTOR0_EVENT_MBX) { + /* Enable interrupt if it is not caused by reset event or error event */ + if (event_cause == HCLGE_VECTOR0_EVENT_MBX || + event_cause == HCLGE_VECTOR0_EVENT_OTHER) hclge_enable_vector(&hdev->misc_vector, true); - }
return IRQ_HANDLED; } @@ -4244,22 +4240,27 @@ static void hclge_misc_err_recovery(struct hclge_dev *hdev) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); struct device *dev = &hdev->pdev->dev; + enum hnae3_reset_type reset_type; u32 msix_sts_reg;
msix_sts_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS); - if (msix_sts_reg & HCLGE_VECTOR0_REG_MSIX_MASK) { - if (hclge_handle_hw_msix_error(hdev, - &hdev->default_reset_request)) + if (hclge_handle_hw_msix_error + (hdev, &hdev->default_reset_request)) dev_info(dev, "received msix interrupt 0x%x\n", msix_sts_reg); + } + hclge_enable_vector(&hdev->misc_vector, true);
- if (hdev->default_reset_request) - if (ae_dev->ops->reset_event) - ae_dev->ops->reset_event(hdev->pdev, NULL); + hclge_handle_hw_ras_error(ae_dev); + if (ae_dev->hw_err_reset_req) { + reset_type = hclge_get_reset_level(ae_dev, + &ae_dev->hw_err_reset_req); + hclge_set_def_reset_request(ae_dev, reset_type); }
- hclge_enable_vector(&hdev->misc_vector, true); + if (hdev->default_reset_request && ae_dev->ops->reset_event) + ae_dev->ops->reset_event(hdev->pdev, NULL); }
static void hclge_errhand_service_task(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 9b8abb5d7a8e..582972a6f60e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -190,6 +190,7 @@ enum HLCGE_PORT_TYPE { #define HCLGE_VECTOR0_IMP_RESET_INT_B 1 #define HCLGE_VECTOR0_IMP_CMDQ_ERR_B 4U #define HCLGE_VECTOR0_IMP_RD_POISON_B 5U +#define HCLGE_VECTOR0_ALL_MSIX_ERR_B 6U
#define HCLGE_MAC_DEFAULT_FRAME \ (ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN)
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 2e2deee7618b062efe3aba9fcb017dadcf148819 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
To adapt to hardware modification and ensure that the driver is compatible with the original error handling content, we need to add the RAS compatibility adaptation solution.
Add a processing branch to the driver during error handling. In the new processing branch, NIC fault information is integrated by the IMP. An interaction command is added between the driver and IMP to query and clear the fault source and interrupt source. The IMP integrates error information and reports the highest reset level to the driver.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_cmd.c | 3 +- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 2 + .../hisilicon/hns3/hns3pf/hclge_err.c | 320 ++++++++++++++++-- .../hisilicon/hns3/hns3pf/hclge_err.h | 69 ++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 54 ++- 5 files changed, 409 insertions(+), 39 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 8f6ed8577aea..614763f5e877 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -178,7 +178,8 @@ static bool hclge_is_special_opcode(u16 opcode) HCLGE_QUERY_CLEAR_MPF_RAS_INT, HCLGE_QUERY_CLEAR_PF_RAS_INT, HCLGE_QUERY_CLEAR_ALL_MPF_MSIX_INT, - HCLGE_QUERY_CLEAR_ALL_PF_MSIX_INT}; + HCLGE_QUERY_CLEAR_ALL_PF_MSIX_INT, + HCLGE_QUERY_ALL_ERR_INFO}; int i;
for (i = 0; i < ARRAY_SIZE(spec_opcode); i++) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index da78a6477e46..234f0a3beec1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -293,6 +293,8 @@ enum hclge_opcode_type { HCLGE_QUERY_MSIX_INT_STS_BD_NUM = 0x1513, HCLGE_QUERY_CLEAR_ALL_MPF_MSIX_INT = 0x1514, HCLGE_QUERY_CLEAR_ALL_PF_MSIX_INT = 0x1515, + HCLGE_QUERY_ALL_ERR_BD_NUM = 0x1516, + HCLGE_QUERY_ALL_ERR_INFO = 0x1517, HCLGE_CONFIG_ROCEE_RAS_INT_EN = 0x1580, HCLGE_QUERY_CLEAR_ROCEE_RAS_INT = 0x1581, HCLGE_ROCEE_PF_RAS_INT_CMD = 0x1584, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 540dd15d7771..36f8055bd859 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -631,6 +631,98 @@ static const struct hclge_hw_error hclge_rocee_qmm_ovf_err_int[] = { { /* sentinel */ } };
+static const struct hclge_hw_module_id hclge_hw_module_id_st[] = { + { + .module_id = MODULE_NONE, + .msg = "MODULE_NONE" + }, { + .module_id = MODULE_BIOS_COMMON, + .msg = "MODULE_BIOS_COMMON" + }, { + .module_id = MODULE_GE, + .msg = "MODULE_GE" + }, { + .module_id = MODULE_IGU_EGU, + .msg = "MODULE_IGU_EGU" + }, { + .module_id = MODULE_LGE, + .msg = "MODULE_LGE" + }, { + .module_id = MODULE_NCSI, + .msg = "MODULE_NCSI" + }, { + .module_id = MODULE_PPP, + .msg = "MODULE_PPP" + }, { + .module_id = MODULE_QCN, + .msg = "MODULE_QCN" + }, { + .module_id = MODULE_RCB_RX, + .msg = "MODULE_RCB_RX" + }, { + .module_id = MODULE_RTC, + .msg = "MODULE_RTC" + }, { + .module_id = MODULE_SSU, + .msg = "MODULE_SSU" + }, { + .module_id = MODULE_TM, + .msg = "MODULE_TM" + }, { + .module_id = MODULE_RCB_TX, + .msg = "MODULE_RCB_TX" + }, { + .module_id = MODULE_TXDMA, + .msg = "MODULE_TXDMA" + }, { + .module_id = MODULE_MASTER, + .msg = "MODULE_MASTER" + } +}; + +static const struct hclge_hw_type_id hclge_hw_type_id_st[] = { + { + .type_id = NONE_ERROR, + .msg = "none_error" + }, { + .type_id = FIFO_ERROR, + .msg = "fifo_error" + }, { + .type_id = MEMORY_ERROR, + .msg = "memory_error" + }, { + .type_id = POISON_ERROR, + .msg = "poison_error" + }, { + .type_id = MSIX_ECC_ERROR, + .msg = "msix_ecc_error" + }, { + .type_id = TQP_INT_ECC_ERROR, + .msg = "tqp_int_ecc_error" + }, { + .type_id = PF_ABNORMAL_INT_ERROR, + .msg = "pf_abnormal_int_error" + }, { + .type_id = MPF_ABNORMAL_INT_ERROR, + .msg = "mpf_abnormal_int_error" + }, { + .type_id = COMMON_ERROR, + .msg = "common_error" + }, { + .type_id = PORT_ERROR, + .msg = "port_error" + }, { + .type_id = ETS_ERROR, + .msg = "ets_error" + }, { + .type_id = NCSI_ERROR, + .msg = "ncsi_error" + }, { + .type_id = GLB_ERROR, + .msg = "glb_error" + } +}; + static void hclge_log_error(struct device *dev, char *reg, const struct hclge_hw_error *err, u32 err_sts, unsigned long *reset_requests) @@ -1892,11 +1984,8 @@ static int hclge_handle_pf_msix_error(struct hclge_dev *hdev, static int hclge_handle_all_hw_msix_error(struct hclge_dev *hdev, unsigned long *reset_requests) { - struct hclge_mac_tnl_stats mac_tnl_stats; - struct device *dev = &hdev->pdev->dev; u32 mpf_bd_num, pf_bd_num, bd_num; struct hclge_desc *desc; - u32 status; int ret;
/* query the number of bds for the MSIx int status */ @@ -1919,29 +2008,7 @@ static int hclge_handle_all_hw_msix_error(struct hclge_dev *hdev, if (ret) goto msi_error;
- /* query and clear mac tnl interruptions */ - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_MAC_TNL_INT, - true); - ret = hclge_cmd_send(&hdev->hw, &desc[0], 1); - if (ret) { - dev_err(dev, "query mac tnl int cmd failed (%d)\n", ret); - goto msi_error; - } - - status = le32_to_cpu(desc->data[0]); - if (status) { - /* When mac tnl interrupt occurs, we record current time and - * register status here in a fifo, then clear the status. So - * that if link status changes suddenly at some time, we can - * query them by debugfs. - */ - mac_tnl_stats.time = local_clock(); - mac_tnl_stats.status = status; - kfifo_put(&hdev->mac_tnl_log, mac_tnl_stats); - ret = hclge_clear_mac_tnl_int(hdev); - if (ret) - dev_err(dev, "clear mac tnl int failed (%d)\n", ret); - } + ret = hclge_handle_mac_tnl(hdev);
msi_error: kfree(desc); @@ -1963,10 +2030,43 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev, return hclge_handle_all_hw_msix_error(hdev, reset_requests); }
-void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev) +int hclge_handle_mac_tnl(struct hclge_dev *hdev) { -#define HCLGE_DESC_NO_DATA_LEN 8 + struct hclge_mac_tnl_stats mac_tnl_stats; + struct device *dev = &hdev->pdev->dev; + struct hclge_desc desc; + u32 status; + int ret;
+ /* query and clear mac tnl interruptions */ + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_MAC_TNL_INT, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(dev, "failed to query mac tnl int, ret = %d.\n", ret); + return ret; + } + + status = le32_to_cpu(desc.data[0]); + if (status) { + /* When mac tnl interrupt occurs, we record current time and + * register status here in a fifo, then clear the status. So + * that if link status changes suddenly at some time, we can + * query them by debugfs. + */ + mac_tnl_stats.time = local_clock(); + mac_tnl_stats.status = status; + kfifo_put(&hdev->mac_tnl_log, mac_tnl_stats); + ret = hclge_clear_mac_tnl_int(hdev); + if (ret) + dev_err(dev, "failed to clear mac tnl int, ret = %d.\n", + ret); + } + + return ret; +} + +void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev) +{ struct hclge_dev *hdev = ae_dev->priv; struct device *dev = &hdev->pdev->dev; u32 mpf_bd_num, pf_bd_num, bd_num; @@ -2015,3 +2115,167 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev) msi_error: kfree(desc); } + +static void +hclge_handle_error_type_reg_log(struct device *dev, + struct hclge_mod_err_info *mod_info, + struct hclge_type_reg_err_info *type_reg_info) +{ +#define HCLGE_ERR_TYPE_MASK 0x7F +#define HCLGE_ERR_TYPE_IS_RAS_OFFSET 7 + + u8 mod_id, total_module, type_id, total_type, i, is_ras; + + mod_id = mod_info->mod_id; + type_id = type_reg_info->type_id & HCLGE_ERR_TYPE_MASK; + is_ras = type_reg_info->type_id >> HCLGE_ERR_TYPE_IS_RAS_OFFSET; + + total_module = ARRAY_SIZE(hclge_hw_module_id_st); + total_type = ARRAY_SIZE(hclge_hw_type_id_st); + + if (mod_id < total_module && type_id < total_type) + dev_err(dev, + "found %s %s, is %s error.\n", + hclge_hw_module_id_st[mod_id].msg, + hclge_hw_type_id_st[type_id].msg, + is_ras ? "ras" : "msix"); + else + dev_err(dev, + "unknown module[%u] or type[%u].\n", mod_id, type_id); + + dev_err(dev, "reg_value:\n"); + for (i = 0; i < type_reg_info->reg_num; i++) + dev_err(dev, "0x%08x\n", type_reg_info->hclge_reg[i]); +} + +static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev, + const u32 *buf, u32 buf_size) +{ + struct hclge_type_reg_err_info *type_reg_info; + struct hclge_dev *hdev = ae_dev->priv; + struct device *dev = &hdev->pdev->dev; + struct hclge_mod_err_info *mod_info; + struct hclge_sum_err_info *sum_info; + u8 mod_num, err_num, i; + u32 offset = 0; + + sum_info = (struct hclge_sum_err_info *)&buf[offset++]; + if (sum_info->reset_type && + sum_info->reset_type != HNAE3_NONE_RESET) + set_bit(sum_info->reset_type, &ae_dev->hw_err_reset_req); + mod_num = sum_info->mod_num; + + while (mod_num--) { + if (offset >= buf_size) { + dev_err(dev, "The offset(%u) exceeds buf's size(%u).\n", + offset, buf_size); + return; + } + mod_info = (struct hclge_mod_err_info *)&buf[offset++]; + err_num = mod_info->err_num; + + for (i = 0; i < err_num; i++) { + if (offset >= buf_size) { + dev_err(dev, + "The offset(%u) exceeds buf size(%u).\n", + offset, buf_size); + return; + } + + type_reg_info = (struct hclge_type_reg_err_info *) + &buf[offset++]; + hclge_handle_error_type_reg_log(dev, mod_info, + type_reg_info); + + offset += type_reg_info->reg_num; + } + } +} + +static int hclge_query_all_err_bd_num(struct hclge_dev *hdev, u32 *bd_num) +{ + struct device *dev = &hdev->pdev->dev; + struct hclge_desc desc_bd; + int ret; + + hclge_cmd_setup_basic_desc(&desc_bd, HCLGE_QUERY_ALL_ERR_BD_NUM, true); + ret = hclge_cmd_send(&hdev->hw, &desc_bd, 1); + if (ret) { + dev_err(dev, "failed to query error bd_num, ret = %d.\n", ret); + return ret; + } + + *bd_num = le32_to_cpu(desc_bd.data[0]); + if (!(*bd_num)) { + dev_err(dev, "The value of bd_num is 0!\n"); + return -EINVAL; + } + + return 0; +} + +static int hclge_query_all_err_info(struct hclge_dev *hdev, + struct hclge_desc *desc, u32 bd_num) +{ + struct device *dev = &hdev->pdev->dev; + int ret; + + hclge_cmd_setup_basic_desc(desc, HCLGE_QUERY_ALL_ERR_INFO, true); + ret = hclge_cmd_send(&hdev->hw, desc, bd_num); + if (ret) + dev_err(dev, "failed to query error info, ret = %d.\n", ret); + + return ret; +} + +int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev) +{ + u32 bd_num, desc_len, buf_len, buf_size, i; + struct hclge_dev *hdev = ae_dev->priv; + struct hclge_desc *desc; + __le32 *desc_data; + u32 *buf; + int ret; + + ret = hclge_query_all_err_bd_num(hdev, &bd_num); + if (ret) + goto out; + + desc_len = bd_num * sizeof(struct hclge_desc); + desc = kzalloc(desc_len, GFP_KERNEL); + if (!desc) { + ret = -ENOMEM; + goto out; + } + + ret = hclge_query_all_err_info(hdev, desc, bd_num); + if (ret) + goto err_desc; + + buf_len = bd_num * sizeof(struct hclge_desc) - HCLGE_DESC_NO_DATA_LEN; + buf_size = buf_len / sizeof(u32); + + desc_data = kzalloc(buf_len, GFP_KERNEL); + if (!desc_data) + return -ENOMEM; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto err_buf_alloc; + } + + memcpy(desc_data, &desc[0].data[0], buf_len); + for (i = 0; i < buf_size; i++) + buf[i] = le32_to_cpu(desc_data[i]); + + hclge_handle_error_module_log(ae_dev, buf, buf_size); + kfree(buf); + +err_buf_alloc: + kfree(desc_data); +err_desc: + kfree(desc); +out: + return ret; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index d647f3c84134..27ab772c665e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -107,6 +107,10 @@ #define HCLGE_ROCEE_OVF_ERR_INT_MASK 0x10000 #define HCLGE_ROCEE_OVF_ERR_TYPE_MASK 0x3F
+#define HCLGE_DESC_DATA_MAX 8 +#define HCLGE_REG_NUM_MAX 256 +#define HCLGE_DESC_NO_DATA_LEN 8 + enum hclge_err_int_type { HCLGE_ERR_INT_MSIX = 0, HCLGE_ERR_INT_RAS_CE = 1, @@ -114,6 +118,40 @@ enum hclge_err_int_type { HCLGE_ERR_INT_RAS_FE = 3, };
+enum hclge_mod_name_list { + MODULE_NONE = 0, + MODULE_BIOS_COMMON = 1, + MODULE_GE = 2, + MODULE_IGU_EGU = 3, + MODULE_LGE = 4, + MODULE_NCSI = 5, + MODULE_PPP = 6, + MODULE_QCN = 7, + MODULE_RCB_RX = 8, + MODULE_RTC = 9, + MODULE_SSU = 10, + MODULE_TM = 11, + MODULE_RCB_TX = 12, + MODULE_TXDMA = 13, + MODULE_MASTER = 14, +}; + +enum hclge_err_type_list { + NONE_ERROR = 0, + FIFO_ERROR = 1, + MEMORY_ERROR = 2, + POISON_ERROR = 3, + MSIX_ECC_ERROR = 4, + TQP_INT_ECC_ERROR = 5, + PF_ABNORMAL_INT_ERROR = 6, + MPF_ABNORMAL_INT_ERROR = 7, + COMMON_ERROR = 8, + PORT_ERROR = 9, + ETS_ERROR = 10, + NCSI_ERROR = 11, + GLB_ERROR = 12, +}; + struct hclge_hw_blk { u32 msk; const char *name; @@ -126,6 +164,35 @@ struct hclge_hw_error { enum hnae3_reset_type reset_level; };
+struct hclge_hw_module_id { + enum hclge_mod_name_list module_id; + const char *msg; +}; + +struct hclge_hw_type_id { + enum hclge_err_type_list type_id; + const char *msg; +}; + +struct hclge_sum_err_info { + u8 reset_type; + u8 mod_num; + u8 rsv[2]; +}; + +struct hclge_mod_err_info { + u8 mod_id; + u8 err_num; + u8 rsv[2]; +}; + +struct hclge_type_reg_err_info { + u8 type_id; + u8 reg_num; + u8 rsv[2]; + u32 hclge_reg[HCLGE_REG_NUM_MAX]; +}; + int hclge_config_mac_tnl_int(struct hclge_dev *hdev, bool en); int hclge_config_nic_hw_error(struct hclge_dev *hdev, bool state); int hclge_config_rocee_ras_interrupt(struct hclge_dev *hdev, bool en); @@ -133,4 +200,6 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev); pci_ers_result_t hclge_handle_hw_ras_error(struct hnae3_ae_dev *ae_dev); int hclge_handle_hw_msix_error(struct hclge_dev *hdev, unsigned long *reset_requests); +int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev); +int hclge_handle_mac_tnl(struct hclge_dev *hdev); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d5be3bc50b5c..3c08fc71b951 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4236,11 +4236,49 @@ static void hclge_reset_subtask(struct hclge_dev *hdev) hdev->reset_type = HNAE3_NONE_RESET; }
+static void hclge_handle_err_reset_request(struct hclge_dev *hdev) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + enum hnae3_reset_type reset_type; + + if (ae_dev->hw_err_reset_req) { + reset_type = hclge_get_reset_level(ae_dev, + &ae_dev->hw_err_reset_req); + hclge_set_def_reset_request(ae_dev, reset_type); + } + + if (hdev->default_reset_request && ae_dev->ops->reset_event) + ae_dev->ops->reset_event(hdev->pdev, NULL); + + /* enable interrupt after error handling complete */ + hclge_enable_vector(&hdev->misc_vector, true); +} + +static void hclge_handle_err_recovery(struct hclge_dev *hdev) +{ + u32 mask_val = HCLGE_RAS_REG_NFE_MASK | HCLGE_RAS_REG_ROCEE_ERR_MASK; + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + u32 msix_src_flag, hw_err_src_flag; + + msix_src_flag = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS) & + HCLGE_VECTOR0_REG_MSIX_MASK; + + hw_err_src_flag = hclge_read_dev(&hdev->hw, + HCLGE_RAS_PF_OTHER_INT_STS_REG) & + mask_val; + + if (msix_src_flag || hw_err_src_flag) { + hclge_handle_error_info_log(ae_dev); + hclge_handle_mac_tnl(hdev); + } + + hclge_handle_err_reset_request(hdev); +} + static void hclge_misc_err_recovery(struct hclge_dev *hdev) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); struct device *dev = &hdev->pdev->dev; - enum hnae3_reset_type reset_type; u32 msix_sts_reg;
msix_sts_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS); @@ -4250,17 +4288,10 @@ static void hclge_misc_err_recovery(struct hclge_dev *hdev) dev_info(dev, "received msix interrupt 0x%x\n", msix_sts_reg); } - hclge_enable_vector(&hdev->misc_vector, true);
hclge_handle_hw_ras_error(ae_dev); - if (ae_dev->hw_err_reset_req) { - reset_type = hclge_get_reset_level(ae_dev, - &ae_dev->hw_err_reset_req); - hclge_set_def_reset_request(ae_dev, reset_type); - }
- if (hdev->default_reset_request && ae_dev->ops->reset_event) - ae_dev->ops->reset_event(hdev->pdev, NULL); + hclge_handle_err_reset_request(hdev); }
static void hclge_errhand_service_task(struct hclge_dev *hdev) @@ -4268,7 +4299,10 @@ static void hclge_errhand_service_task(struct hclge_dev *hdev) if (!test_and_clear_bit(HCLGE_STATE_ERR_SERVICE_SCHED, &hdev->state)) return;
- hclge_misc_err_recovery(hdev); + if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) + hclge_handle_err_recovery(hdev); + else + hclge_misc_err_recovery(hdev); }
static void hclge_reset_service_task(struct hclge_dev *hdev)
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit e65e9f5c2e4efc17657d016d767eb7010d9dd598 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
IMP(Intelligent Management Processor) firmware add a new feature to handle and consolidate RAS information for new devices, NIC driver only needs to query the reported RAS information. NIC driver adds support for this feature.
Driver queries device capability to check whether IMP support this feature, If yes, execute the new RAS processing branch.
In order to add a method to check whether PF supports imp-handle RAS feature, add dumping this info in debugfs.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 ++++ drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 3 +++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 2 ++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 5 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index bf10652f07ee..8e8e2bd2acea 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -90,6 +90,7 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_STASH_B, HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, HNAE3_DEV_SUPPORT_PAUSE_B, + HNAE3_DEV_SUPPORT_RAS_IMP_B, HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, @@ -128,6 +129,9 @@ enum HNAE3_DEV_CAP_BITS { #define hnae3_dev_phy_imp_supported(hdev) \ test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, (hdev)->ae_dev->caps)
+#define hnae3_dev_ras_imp_supported(hdev) \ + test_bit(HNAE3_DEV_SUPPORT_RAS_IMP_B, (hdev)->ae_dev->caps) + #define hnae3_dev_tqp_txrx_indep_supported(hdev) \ test_bit(HNAE3_DEV_SUPPORT_TQP_TXRX_INDEP_B, (hdev)->ae_dev->caps)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index cf1efd2f4a0f..a0edca848392 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -349,6 +349,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { }, { .name = "support imp-controlled PHY", .cap_bit = HNAE3_DEV_SUPPORT_PHY_IMP_B, + }, { + .name = "support imp-controlled RAS", + .cap_bit = HNAE3_DEV_SUPPORT_RAS_IMP_B, }, { .name = "support rxd advanced layout", .cap_bit = HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 614763f5e877..887297e37cf3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -387,6 +387,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev, set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_PHY_IMP_B)) set_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps); + if (hnae3_get_bit(caps, HCLGE_CAP_RAS_IMP_B)) + set_bit(HNAE3_DEV_SUPPORT_RAS_IMP_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_RXD_ADV_LAYOUT_B)) set_bit(HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, ae_dev->caps); if (hnae3_get_bit(caps, HCLGE_CAP_PORT_VLAN_BYPASS_B)) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 234f0a3beec1..221811af9473 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -392,6 +392,7 @@ enum HCLGE_CAP_BITS { HCLGE_CAP_HW_PAD_B, HCLGE_CAP_STASH_B, HCLGE_CAP_UDP_TUNNEL_CSUM_B, + HCLGE_CAP_RAS_IMP_B = 12, HCLGE_CAP_FEC_B = 13, HCLGE_CAP_PAUSE_B = 14, HCLGE_CAP_RXD_ADV_LAYOUT_B = 15, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3c08fc71b951..cf34216df171 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4299,7 +4299,7 @@ static void hclge_errhand_service_task(struct hclge_dev *hdev) if (!test_and_clear_bit(HCLGE_STATE_ERR_SERVICE_SCHED, &hdev->state)) return;
- if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) + if (hnae3_dev_ras_imp_supported(hdev)) hclge_handle_err_recovery(hdev); else hclge_misc_err_recovery(hdev);
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 8a95e360fd512f1cb55239645879b15d26bc7e21 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Update error recovery module and type for RoCE.
The enumeration values of module names and error types are not sorted in sequence. If use the current printing mode, they cannot be correctly printed.
Use the index mode, If mod_id and type_id match the enumerated value, display the corresponding information.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Weihang Li liweihang@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_err.c | 58 ++++++++++++++++++- .../hisilicon/hns3/hns3pf/hclge_err.h | 18 ++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 3 +- 3 files changed, 74 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 36f8055bd859..0e942d11dbf3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -677,6 +677,36 @@ static const struct hclge_hw_module_id hclge_hw_module_id_st[] = { }, { .module_id = MODULE_MASTER, .msg = "MODULE_MASTER" + }, { + .module_id = MODULE_ROCEE_TOP, + .msg = "MODULE_ROCEE_TOP" + }, { + .module_id = MODULE_ROCEE_TIMER, + .msg = "MODULE_ROCEE_TIMER" + }, { + .module_id = MODULE_ROCEE_MDB, + .msg = "MODULE_ROCEE_MDB" + }, { + .module_id = MODULE_ROCEE_TSP, + .msg = "MODULE_ROCEE_TSP" + }, { + .module_id = MODULE_ROCEE_TRP, + .msg = "MODULE_ROCEE_TRP" + }, { + .module_id = MODULE_ROCEE_SCC, + .msg = "MODULE_ROCEE_SCC" + }, { + .module_id = MODULE_ROCEE_CAEP, + .msg = "MODULE_ROCEE_CAEP" + }, { + .module_id = MODULE_ROCEE_GEN_AC, + .msg = "MODULE_ROCEE_GEN_AC" + }, { + .module_id = MODULE_ROCEE_QMM, + .msg = "MODULE_ROCEE_QMM" + }, { + .module_id = MODULE_ROCEE_LSAN, + .msg = "MODULE_ROCEE_LSAN" } };
@@ -720,6 +750,12 @@ static const struct hclge_hw_type_id hclge_hw_type_id_st[] = { }, { .type_id = GLB_ERROR, .msg = "glb_error" + }, { + .type_id = ROCEE_NORMAL_ERR, + .msg = "rocee_normal_error" + }, { + .type_id = ROCEE_OVF_ERR, + .msg = "rocee_ovf_error" } };
@@ -2125,6 +2161,8 @@ hclge_handle_error_type_reg_log(struct device *dev, #define HCLGE_ERR_TYPE_IS_RAS_OFFSET 7
u8 mod_id, total_module, type_id, total_type, i, is_ras; + u8 index_module = MODULE_NONE; + u8 index_type = NONE_ERROR;
mod_id = mod_info->mod_id; type_id = type_reg_info->type_id & HCLGE_ERR_TYPE_MASK; @@ -2133,11 +2171,25 @@ hclge_handle_error_type_reg_log(struct device *dev, total_module = ARRAY_SIZE(hclge_hw_module_id_st); total_type = ARRAY_SIZE(hclge_hw_type_id_st);
- if (mod_id < total_module && type_id < total_type) + for (i = 0; i < total_module; i++) { + if (mod_id == hclge_hw_module_id_st[i].module_id) { + index_module = i; + break; + } + } + + for (i = 0; i < total_type; i++) { + if (type_id == hclge_hw_type_id_st[i].type_id) { + index_type = i; + break; + } + } + + if (index_module != MODULE_NONE && index_type != NONE_ERROR) dev_err(dev, "found %s %s, is %s error.\n", - hclge_hw_module_id_st[mod_id].msg, - hclge_hw_type_id_st[type_id].msg, + hclge_hw_module_id_st[index_module].msg, + hclge_hw_type_id_st[index_type].msg, is_ras ? "ras" : "msix"); else dev_err(dev, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index 27ab772c665e..ce4c96bbef8e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -15,6 +15,8 @@ #define HCLGE_RAS_PF_OTHER_INT_STS_REG 0x20B00 #define HCLGE_RAS_REG_NFE_MASK 0xFF00 #define HCLGE_RAS_REG_ROCEE_ERR_MASK 0x3000000 +#define HCLGE_RAS_REG_ERR_MASK \ + (HCLGE_RAS_REG_NFE_MASK | HCLGE_RAS_REG_ROCEE_ERR_MASK)
#define HCLGE_VECTOR0_REG_MSIX_MASK 0x1FF00
@@ -134,6 +136,18 @@ enum hclge_mod_name_list { MODULE_RCB_TX = 12, MODULE_TXDMA = 13, MODULE_MASTER = 14, + /* add new MODULE NAME for NIC here in order */ + MODULE_ROCEE_TOP = 40, + MODULE_ROCEE_TIMER = 41, + MODULE_ROCEE_MDB = 42, + MODULE_ROCEE_TSP = 43, + MODULE_ROCEE_TRP = 44, + MODULE_ROCEE_SCC = 45, + MODULE_ROCEE_CAEP = 46, + MODULE_ROCEE_GEN_AC = 47, + MODULE_ROCEE_QMM = 48, + MODULE_ROCEE_LSAN = 49, + /* add new MODULE NAME for RoCEE here in order */ };
enum hclge_err_type_list { @@ -150,6 +164,10 @@ enum hclge_err_type_list { ETS_ERROR = 10, NCSI_ERROR = 11, GLB_ERROR = 12, + /* add new ERROR TYPE for NIC here in order */ + ROCEE_NORMAL_ERR = 40, + ROCEE_OVF_ERR = 41, + /* add new ERROR TYPE for ROCEE here in order */ };
struct hclge_hw_blk { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index cf34216df171..9ff4210f6477 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3343,8 +3343,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
/* check for vector0 msix event and hardware error event source */ if (msix_src_reg & HCLGE_VECTOR0_REG_MSIX_MASK || - hw_err_src_reg & HCLGE_RAS_REG_NFE_MASK || - hw_err_src_reg & HCLGE_RAS_REG_ROCEE_ERR_MASK) + hw_err_src_reg & HCLGE_RAS_REG_ERR_MASK) return HCLGE_VECTOR0_EVENT_ERR;
/* check for vector0 mailbox(=CMDQ RX) event source */
From: Jiaran Zhang zhangjiaran@huawei.com
mainline inclusion from mainline-master commit 1c360a4a077fc0f74a350fe2ef267cbe8a9388e3 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
During initialization, the driver logs and clears the hw errors that already occurred. For device supports imp-handle ras capability, it needs handle different error status, otherwise it may cause wrong reset.
So fix it by adding a new processing branch.
Signed-off-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../hisilicon/hns3/hns3pf/hclge_err.c | 22 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_err.h | 2 ++ .../hisilicon/hns3/hns3pf/hclge_main.c | 21 +++++++++--------- 3 files changed, 34 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 0e942d11dbf3..bad9fda19398 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -2152,6 +2152,28 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev) kfree(desc); }
+bool hclge_find_error_source(struct hclge_dev *hdev) +{ + u32 msix_src_flag, hw_err_src_flag; + + msix_src_flag = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS) & + HCLGE_VECTOR0_REG_MSIX_MASK; + + hw_err_src_flag = hclge_read_dev(&hdev->hw, + HCLGE_RAS_PF_OTHER_INT_STS_REG) & + HCLGE_RAS_REG_ERR_MASK; + + return msix_src_flag || hw_err_src_flag; +} + +void hclge_handle_occurred_error(struct hclge_dev *hdev) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + + if (hclge_find_error_source(hdev)) + hclge_handle_error_info_log(ae_dev); +} + static void hclge_handle_error_type_reg_log(struct device *dev, struct hclge_mod_err_info *mod_info, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index ce4c96bbef8e..07987fb8332e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -215,6 +215,8 @@ int hclge_config_mac_tnl_int(struct hclge_dev *hdev, bool en); int hclge_config_nic_hw_error(struct hclge_dev *hdev, bool state); int hclge_config_rocee_ras_interrupt(struct hclge_dev *hdev, bool en); void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev); +bool hclge_find_error_source(struct hclge_dev *hdev); +void hclge_handle_occurred_error(struct hclge_dev *hdev); pci_ers_result_t hclge_handle_hw_ras_error(struct hnae3_ae_dev *ae_dev); int hclge_handle_hw_msix_error(struct hclge_dev *hdev, unsigned long *reset_requests); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9ff4210f6477..d960e08850ae 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4255,18 +4255,11 @@ static void hclge_handle_err_reset_request(struct hclge_dev *hdev)
static void hclge_handle_err_recovery(struct hclge_dev *hdev) { - u32 mask_val = HCLGE_RAS_REG_NFE_MASK | HCLGE_RAS_REG_ROCEE_ERR_MASK; struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); - u32 msix_src_flag, hw_err_src_flag;
- msix_src_flag = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS) & - HCLGE_VECTOR0_REG_MSIX_MASK; + ae_dev->hw_err_reset_req = 0;
- hw_err_src_flag = hclge_read_dev(&hdev->hw, - HCLGE_RAS_PF_OTHER_INT_STS_REG) & - mask_val; - - if (msix_src_flag || hw_err_src_flag) { + if (hclge_find_error_source(hdev)) { hclge_handle_error_info_log(ae_dev); hclge_handle_mac_tnl(hdev); } @@ -11558,7 +11551,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_clear_resetting_state(hdev);
/* Log and clear the hw errors those already occurred */ - hclge_handle_all_hns_hw_errors(ae_dev); + if (hnae3_dev_ras_imp_supported(hdev)) + hclge_handle_occurred_error(hdev); + else + hclge_handle_all_hns_hw_errors(ae_dev);
/* request delayed reset for the error recovery because an immediate * global reset on a PF affecting pending initialization of other PFs @@ -11911,7 +11907,10 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) }
/* Log and clear the hw errors those already occurred */ - hclge_handle_all_hns_hw_errors(ae_dev); + if (hnae3_dev_ras_imp_supported(hdev)) + hclge_handle_occurred_error(hdev); + else + hclge_handle_all_hns_hw_errors(ae_dev);
/* Re-enable the hw error interrupts because * the interrupts get disabled on global reset.
From: Baokun Li libaokun1@huawei.com
mainline inclusion from mainline-master commit 49768ce98c2c1766619dfd6d157dd87826738fa7 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Using list_move_tail() instead of list_del() + list_add_tail() in hclgevf_main.c.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Baokun Li libaokun1@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index f84b3a135c06..52eaf82b7cd7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1536,8 +1536,7 @@ static void hclgevf_sync_from_add_list(struct list_head *add_list, kfree(mac_node); } else if (mac_node->state == HCLGEVF_MAC_ACTIVE) { mac_node->state = HCLGEVF_MAC_TO_DEL; - list_del(&mac_node->node); - list_add_tail(&mac_node->node, mac_list); + list_move_tail(&mac_node->node, mac_list); } else { list_del(&mac_node->node); kfree(mac_node); @@ -1562,8 +1561,7 @@ static void hclgevf_sync_from_del_list(struct list_head *del_list, list_del(&mac_node->node); kfree(mac_node); } else { - list_del(&mac_node->node); - list_add_tail(&mac_node->node, mac_list); + list_move_tail(&mac_node->node, mac_list); } } } @@ -1599,8 +1597,7 @@ static void hclgevf_sync_mac_list(struct hclgevf_dev *hdev, list_for_each_entry_safe(mac_node, tmp, list, node) { switch (mac_node->state) { case HCLGEVF_MAC_TO_DEL: - list_del(&mac_node->node); - list_add_tail(&mac_node->node, &tmp_del_list); + list_move_tail(&mac_node->node, &tmp_del_list); break; case HCLGEVF_MAC_TO_ADD: new_node = kzalloc(sizeof(*new_node), GFP_ATOMIC);
From: Baokun Li libaokun1@huawei.com
mainline inclusion from mainline-master commit 4724acc47c9441ec1e131299853d1a9e8c3fb2cd category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Using list_move_tail() instead of list_del() + list_add_tail() in hclge_main.c.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Baokun Li libaokun1@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d960e08850ae..c90d7c1550c5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8834,8 +8834,7 @@ static bool hclge_sync_from_add_list(struct list_head *add_list, kfree(mac_node); } else if (mac_node->state == HCLGE_MAC_ACTIVE) { mac_node->state = HCLGE_MAC_TO_DEL; - list_del(&mac_node->node); - list_add_tail(&mac_node->node, mac_list); + list_move_tail(&mac_node->node, mac_list); } else { list_del(&mac_node->node); kfree(mac_node); @@ -8864,8 +8863,7 @@ static void hclge_sync_from_del_list(struct list_head *del_list, list_del(&mac_node->node); kfree(mac_node); } else { - list_del(&mac_node->node); - list_add_tail(&mac_node->node, mac_list); + list_move_tail(&mac_node->node, mac_list); } } } @@ -8909,8 +8907,7 @@ static void hclge_sync_vport_mac_table(struct hclge_vport *vport, list_for_each_entry_safe(mac_node, tmp, list, node) { switch (mac_node->state) { case HCLGE_MAC_TO_DEL: - list_del(&mac_node->node); - list_add_tail(&mac_node->node, &tmp_del_list); + list_move_tail(&mac_node->node, &tmp_del_list); break; case HCLGE_MAC_TO_ADD: new_node = kzalloc(sizeof(*new_node), GFP_ATOMIC); @@ -8992,8 +8989,7 @@ static void hclge_build_del_list(struct list_head *list, switch (mac_cfg->state) { case HCLGE_MAC_TO_DEL: case HCLGE_MAC_ACTIVE: - list_del(&mac_cfg->node); - list_add_tail(&mac_cfg->node, tmp_del_list); + list_move_tail(&mac_cfg->node, tmp_del_list); break; case HCLGE_MAC_TO_ADD: if (is_del_list) { @@ -9088,8 +9084,7 @@ static void hclge_uninit_vport_mac_list(struct hclge_vport *vport, switch (mac_node->state) { case HCLGE_MAC_TO_DEL: case HCLGE_MAC_ACTIVE: - list_del(&mac_node->node); - list_add_tail(&mac_node->node, &tmp_del_list); + list_move_tail(&mac_node->node, &tmp_del_list); break; case HCLGE_MAC_TO_ADD: list_del(&mac_node->node);
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 0bf5eb788512187b744ef7f79de835e6cbe85b9c category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Adds PTP support for HNS3 ethernet driver.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/Kconfig | 1 + drivers/net/ethernet/hisilicon/hns3/hnae3.h | 12 + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 27 + .../net/ethernet/hisilicon/hns3/hns3_enet.h | 9 +- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 12 + .../ethernet/hisilicon/hns3/hns3pf/Makefile | 2 +- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 4 + .../hisilicon/hns3/hns3pf/hclge_main.c | 61 +- .../hisilicon/hns3/hns3pf/hclge_main.h | 6 + .../hisilicon/hns3/hns3pf/hclge_ptp.c | 544 ++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_ptp.h | 134 +++++ 11 files changed, 806 insertions(+), 6 deletions(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index fa6025dc4cdb..bb062b02fb85 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -102,6 +102,7 @@ config HNS3_HCLGE tristate "Hisilicon HNS3 HCLGE Acceleration Engine & Compatibility Layer Support" default m depends on PCI_MSI + imply PTP_1588_CLOCK help This selects the HNS3_HCLGE network acceleration engine & its hardware compatibility layer. The engine would be used in Hisilicon hip08 family of diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 8e8e2bd2acea..89f45384ca13 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -524,6 +524,12 @@ struct hnae3_ae_dev { * Check if any cls flower rule exist * dbg_read_cmd * Execute debugfs read command. + * set_tx_hwts_info + * Save information for 1588 tx packet + * get_rx_hwts + * Get 1588 rx hwstamp + * get_ts_info + * Get phc info */ struct hnae3_ae_ops { int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev); @@ -709,6 +715,12 @@ struct hnae3_ae_ops { struct ethtool_link_ksettings *cmd); int (*set_phy_link_ksettings)(struct hnae3_handle *handle, const struct ethtool_link_ksettings *cmd); + bool (*set_tx_hwts_info)(struct hnae3_handle *handle, + struct sk_buff *skb); + void (*get_rx_hwts)(struct hnae3_handle *handle, struct sk_buff *skb, + u32 nsec, u32 sec); + int (*get_ts_info)(struct hnae3_handle *handle, + struct ethtool_ts_info *info); };
struct hnae3_dcb_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 393979bec170..9a45f3cde6a2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1799,6 +1799,18 @@ static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num, WRITE_ONCE(ring->last_to_use, ring->next_to_use); }
+static void hns3_tsyn(struct net_device *netdev, struct sk_buff *skb, + struct hns3_desc *desc) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (!(h->ae_algo->ops->set_tx_hwts_info && + h->ae_algo->ops->set_tx_hwts_info(h, skb))) + return; + + desc->tx.bdtp_fe_sc_vld_ra_ri |= cpu_to_le16(BIT(HNS3_TXD_TSYN_B)); +} + netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -1851,10 +1863,16 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) : (ring->desc_num - 1); + + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) + hns3_tsyn(netdev, skb, &ring->desc[pre_ntu]); + ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |= cpu_to_le16(BIT(HNS3_TXD_FE_B)); trace_hns3_tx_desc(ring, pre_ntu);
+ skb_tx_timestamp(skb); + /* Complete translate all packets */ dev_queue = netdev_get_tx_queue(netdev, ring->queue_index); doorbell = __netdev_tx_sent_queue(dev_queue, desc_cb->send_bytes, @@ -3585,6 +3603,15 @@ static int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb) ol_info = le32_to_cpu(desc->rx.ol_info); csum = le16_to_cpu(desc->csum);
+ if (unlikely(bd_base_info & BIT(HNS3_RXD_TS_VLD_B))) { + struct hnae3_handle *h = hns3_get_handle(netdev); + u32 nsec = le32_to_cpu(desc->ts_nsec); + u32 sec = le32_to_cpu(desc->ts_sec); + + if (h->ae_algo->ops->get_rx_hwts) + h->ae_algo->ops->get_rx_hwts(h, skb, nsec, sec); + } + /* Based on hw strategy, the tag offloaded will be stored at * ot_vlan_tag in two layer tag case, and stored at vlan_tag * in one layer tag case. diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 5698a14a804e..79821c7bdc16 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -122,8 +122,9 @@ enum hns3_nic_state { #define HNS3_RXD_LUM_B 9 #define HNS3_RXD_CRCP_B 10 #define HNS3_RXD_L3L4P_B 11 -#define HNS3_RXD_TSIND_S 12 -#define HNS3_RXD_TSIND_M (0x7 << HNS3_RXD_TSIND_S) +#define HNS3_RXD_TSIDX_S 12 +#define HNS3_RXD_TSIDX_M (0x3 << HNS3_RXD_TSIDX_S) +#define HNS3_RXD_TS_VLD_B 14 #define HNS3_RXD_LKBK_B 15 #define HNS3_RXD_GRO_SIZE_S 16 #define HNS3_RXD_GRO_SIZE_M (0x3fff << HNS3_RXD_GRO_SIZE_S) @@ -240,6 +241,10 @@ struct __packed hns3_desc { union { __le64 addr; __le16 csum; + struct { + __le32 ts_nsec; + __le32 ts_sec; + }; }; union { struct { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index bb7c2ec7ed6f..acef5435d7b7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -1598,6 +1598,17 @@ static int hns3_set_priv_flags(struct net_device *netdev, u32 pflags) ETHTOOL_COALESCE_TX_USECS_HIGH | \ ETHTOOL_COALESCE_MAX_FRAMES)
+static int hns3_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info) +{ + struct hnae3_handle *handle = hns3_get_handle(netdev); + + if (handle->ae_algo->ops->get_ts_info) + return handle->ae_algo->ops->get_ts_info(handle, info); + + return ethtool_op_get_ts_info(netdev, info); +} + static const struct ethtool_ops hns3vf_ethtool_ops = { .supported_coalesce_params = HNS3_ETHTOOL_COALESCE, .get_drvinfo = hns3_get_drvinfo, @@ -1662,6 +1673,7 @@ static const struct ethtool_ops hns3_ethtool_ops = { .get_module_eeprom = hns3_get_module_eeprom, .get_priv_flags = hns3_get_priv_flags, .set_priv_flags = hns3_set_priv_flags, + .get_ts_info = hns3_get_ts_info, };
void hns3_ethtool_set_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile index 6c28c8f6292c..a685392dbfe9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile @@ -7,6 +7,6 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3 ccflags-y += -I $(srctree)/$(src)
obj-$(CONFIG_HNS3_HCLGE) += hclge.o -hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge_debugfs.o +hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge_debugfs.o hclge_ptp.o
hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 221811af9473..51be76f1795e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -130,6 +130,10 @@ enum hclge_opcode_type { HCLGE_OPC_COMMON_LOOPBACK = 0x0315, HCLGE_OPC_CONFIG_FEC_MODE = 0x031A,
+ /* PTP commands */ + HCLGE_OPC_PTP_INT_EN = 0x0501, + HCLGE_OPC_PTP_MODE_CFG = 0x0507, + /* PFC/Pause commands */ HCLGE_OPC_CFG_MAC_PAUSE_EN = 0x0701, HCLGE_OPC_CFG_PFC_PAUSE_EN = 0x0702, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c90d7c1550c5..f6fdf93c8cad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3346,6 +3346,12 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) hw_err_src_reg & HCLGE_RAS_REG_ERR_MASK) return HCLGE_VECTOR0_EVENT_ERR;
+ /* check for vector0 ptp event source */ + if (BIT(HCLGE_VECTOR0_REG_PTP_INT_B) & msix_src_reg) { + *clearval = msix_src_reg; + return HCLGE_VECTOR0_EVENT_PTP; + } + /* check for vector0 mailbox(=CMDQ RX) event source */ if (BIT(HCLGE_VECTOR0_RX_CMDQ_INT_B) & cmdq_src_reg) { cmdq_src_reg &= ~BIT(HCLGE_VECTOR0_RX_CMDQ_INT_B); @@ -3365,6 +3371,7 @@ static void hclge_clear_event_cause(struct hclge_dev *hdev, u32 event_type, u32 regclr) { switch (event_type) { + case HCLGE_VECTOR0_EVENT_PTP: case HCLGE_VECTOR0_EVENT_RST: hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, regclr); break; @@ -3393,6 +3400,7 @@ static void hclge_enable_vector(struct hclge_misc_vector *vector, bool enable) static irqreturn_t hclge_misc_irq_handle(int irq, void *data) { struct hclge_dev *hdev = data; + unsigned long flags; u32 clearval = 0; u32 event_cause;
@@ -3407,6 +3415,11 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) case HCLGE_VECTOR0_EVENT_RST: hclge_reset_task_schedule(hdev); break; + case HCLGE_VECTOR0_EVENT_PTP: + spin_lock_irqsave(&hdev->ptp->lock, flags); + hclge_ptp_clean_tx_hwts(hdev); + spin_unlock_irqrestore(&hdev->ptp->lock, flags); + break; case HCLGE_VECTOR0_EVENT_MBX: /* If we are here then, * 1. Either we are not handling any mbx task and we are not @@ -3428,7 +3441,8 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) hclge_clear_event_cause(hdev, event_cause, clearval);
/* Enable interrupt if it is not caused by reset event or error event */ - if (event_cause == HCLGE_VECTOR0_EVENT_MBX || + if (event_cause == HCLGE_VECTOR0_EVENT_PTP || + event_cause == HCLGE_VECTOR0_EVENT_MBX || event_cause == HCLGE_VECTOR0_EVENT_OTHER) hclge_enable_vector(&hdev->misc_vector, true);
@@ -4375,6 +4389,27 @@ static void hclge_periodic_service_task(struct hclge_dev *hdev) hclge_task_schedule(hdev, delta); }
+static void hclge_ptp_service_task(struct hclge_dev *hdev) +{ + unsigned long flags; + + if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state) || + !test_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state) || + !time_is_before_jiffies(hdev->ptp->tx_start + HZ)) + return; + + /* to prevent concurrence with the irq handler */ + spin_lock_irqsave(&hdev->ptp->lock, flags); + + /* check HCLGE_STATE_PTP_TX_HANDLING here again, since the irq + * handler may handle it just before spin_lock_irqsave(). + */ + if (test_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state)) + hclge_ptp_clean_tx_hwts(hdev); + + spin_unlock_irqrestore(&hdev->ptp->lock, flags); +} + static void hclge_service_task(struct work_struct *work) { struct hclge_dev *hdev = @@ -4382,6 +4417,7 @@ static void hclge_service_task(struct work_struct *work)
hclge_errhand_service_task(hdev); hclge_reset_service_task(hdev); + hclge_ptp_service_task(hdev); hclge_mailbox_service_task(hdev); hclge_periodic_service_task(hdev);
@@ -9413,8 +9449,15 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back;
- if (!hdev->hw.mac.phydev) - return hclge_mii_ioctl(hdev, ifr, cmd); + switch (cmd) { + case SIOCGHWTSTAMP: + return hclge_ptp_get_cfg(hdev, ifr); + case SIOCSHWTSTAMP: + return hclge_ptp_set_cfg(hdev, ifr); + default: + if (!hdev->hw.mac.phydev) + return hclge_mii_ioctl(hdev, ifr, cmd); + }
return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd); } @@ -11530,6 +11573,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) goto err_mdiobus_unreg; }
+ ret = hclge_ptp_init(hdev); + if (ret) + goto err_mdiobus_unreg; + INIT_KFIFO(hdev->mac_tnl_log);
hclge_dcb_ops_set(hdev); @@ -11901,6 +11948,10 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; }
+ ret = hclge_ptp_init(hdev); + if (ret) + return ret; + /* Log and clear the hw errors those already occurred */ if (hnae3_dev_ras_imp_supported(hdev)) hclge_handle_occurred_error(hdev); @@ -11954,6 +12005,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_clear_vf_vlan(hdev); hclge_misc_affinity_teardown(hdev); hclge_state_uninit(hdev); + hclge_ptp_uninit(hdev); hclge_uninit_rxd_adv_layout(hdev); hclge_uninit_mac_table(hdev); hclge_del_all_fd_entries(hdev); @@ -12850,6 +12902,9 @@ static const struct hnae3_ae_ops hclge_ops = { .cls_flower_active = hclge_is_cls_flower_active, .get_phy_link_ksettings = hclge_get_phy_link_ksettings, .set_phy_link_ksettings = hclge_set_phy_link_ksettings, + .set_tx_hwts_info = hclge_ptp_set_tx_info, + .get_rx_hwts = hclge_ptp_get_rx_hwts, + .get_ts_info = hclge_ptp_get_ts_info, };
static struct hnae3_ae_algo ae_algo = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 582972a6f60e..02852738ce21 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -10,6 +10,7 @@ #include <linux/kfifo.h>
#include "hclge_cmd.h" +#include "hclge_ptp.h" #include "hnae3.h"
#define HCLGE_MOD_VERSION "1.0" @@ -178,6 +179,7 @@ enum HLCGE_PORT_TYPE { #define HCLGE_FUN_RST_ING_B 0
/* Vector0 register bits define */ +#define HCLGE_VECTOR0_REG_PTP_INT_B 0 #define HCLGE_VECTOR0_GLOBALRESET_INT_B 5 #define HCLGE_VECTOR0_CORERESET_INT_B 6 #define HCLGE_VECTOR0_IMPRESET_INT_B 7 @@ -230,6 +232,8 @@ enum HCLGE_DEV_STATE { HCLGE_STATE_FD_TBL_CHANGED, HCLGE_STATE_FD_CLEAR_ALL, HCLGE_STATE_FD_USER_DEF_CHANGED, + HCLGE_STATE_PTP_EN, + HCLGE_STATE_PTP_TX_HANDLING, HCLGE_STATE_MAX };
@@ -237,6 +241,7 @@ enum hclge_evt_cause { HCLGE_VECTOR0_EVENT_RST, HCLGE_VECTOR0_EVENT_MBX, HCLGE_VECTOR0_EVENT_ERR, + HCLGE_VECTOR0_EVENT_PTP, HCLGE_VECTOR0_EVENT_OTHER, };
@@ -935,6 +940,7 @@ struct hclge_dev { /* affinity mask and notify for misc interrupt */ cpumask_t affinity_mask; struct irq_affinity_notify affinity_notify; + struct hclge_ptp *ptp; };
/* VPort level vlan tag configuration for TX direction */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c new file mode 100644 index 000000000000..b3eb8f109dbb --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2021 Hisilicon Limited. + +#include <linux/skbuff.h> +#include "hclge_main.h" +#include "hnae3.h" + +static int hclge_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp); + u64 adj_val, adj_base, diff; + unsigned long flags; + bool is_neg = false; + u32 quo, numerator; + + if (ppb < 0) { + ppb = -ppb; + is_neg = true; + } + + adj_base = HCLGE_PTP_CYCLE_ADJ_BASE * HCLGE_PTP_CYCLE_ADJ_UNIT; + adj_val = adj_base * ppb; + diff = div_u64(adj_val, 1000000000ULL); + + if (is_neg) + adj_val = adj_base - diff; + else + adj_val = adj_base + diff; + + /* This clock cycle is defined by three part: quotient, numerator + * and denominator. For example, 2.5ns, the quotient is 2, + * denominator is fixed to HCLGE_PTP_CYCLE_ADJ_UNIT, and numerator + * is 0.5 * HCLGE_PTP_CYCLE_ADJ_UNIT. + */ + quo = div_u64_rem(adj_val, HCLGE_PTP_CYCLE_ADJ_UNIT, &numerator); + + spin_lock_irqsave(&hdev->ptp->lock, flags); + writel(quo, hdev->ptp->io_base + HCLGE_PTP_CYCLE_QUO_REG); + writel(numerator, hdev->ptp->io_base + HCLGE_PTP_CYCLE_NUM_REG); + writel(HCLGE_PTP_CYCLE_ADJ_UNIT, + hdev->ptp->io_base + HCLGE_PTP_CYCLE_DEN_REG); + writel(HCLGE_PTP_CYCLE_ADJ_EN, + hdev->ptp->io_base + HCLGE_PTP_CYCLE_CFG_REG); + spin_unlock_irqrestore(&hdev->ptp->lock, flags); + + return 0; +} + +bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + struct hclge_ptp *ptp = hdev->ptp; + + if (!test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) || + test_and_set_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state)) { + ptp->tx_skipped++; + return false; + } + + ptp->tx_start = jiffies; + ptp->tx_skb = skb_get(skb); + ptp->tx_cnt++; + + return true; +} + +void hclge_ptp_clean_tx_hwts(struct hclge_dev *hdev) +{ + struct sk_buff *skb = hdev->ptp->tx_skb; + struct skb_shared_hwtstamps hwts; + u32 hi, lo; + u64 ns; + + ns = readl(hdev->ptp->io_base + HCLGE_PTP_TX_TS_NSEC_REG) & + HCLGE_PTP_TX_TS_NSEC_MASK; + lo = readl(hdev->ptp->io_base + HCLGE_PTP_TX_TS_SEC_L_REG); + hi = readl(hdev->ptp->io_base + HCLGE_PTP_TX_TS_SEC_H_REG) & + HCLGE_PTP_TX_TS_SEC_H_MASK; + hdev->ptp->last_tx_seqid = readl(hdev->ptp->io_base + + HCLGE_PTP_TX_TS_SEQID_REG); + + if (skb) { + hdev->ptp->tx_skb = NULL; + hdev->ptp->tx_cleaned++; + + ns += (((u64)hi) << 32 | lo) * NSEC_PER_SEC; + hwts.hwtstamp = ns_to_ktime(ns); + skb_tstamp_tx(skb, &hwts); + dev_kfree_skb_any(skb); + } + + clear_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state); +} + +void hclge_ptp_get_rx_hwts(struct hnae3_handle *handle, struct sk_buff *skb, + u32 nsec, u32 sec) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + unsigned long flags; + u64 ns = nsec; + u32 sec_h; + + if (!test_bit(HCLGE_PTP_FLAG_RX_EN, &hdev->ptp->flags)) + return; + + /* Since the BD does not have enough space for the higher 16 bits of + * second, and this part will not change frequently, so read it + * from register. + */ + spin_lock_irqsave(&hdev->ptp->lock, flags); + sec_h = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_SEC_H_REG); + spin_unlock_irqrestore(&hdev->ptp->lock, flags); + + ns += (((u64)sec_h) << HCLGE_PTP_SEC_H_OFFSET | sec) * NSEC_PER_SEC; + skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns); + hdev->ptp->last_rx = jiffies; + hdev->ptp->rx_cnt++; +} + +static int hclge_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp); + unsigned long flags; + u32 hi, lo; + u64 ns; + + spin_lock_irqsave(&hdev->ptp->lock, flags); + ns = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_NSEC_REG); + hi = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_SEC_H_REG); + lo = readl(hdev->ptp->io_base + HCLGE_PTP_CUR_TIME_SEC_L_REG); + spin_unlock_irqrestore(&hdev->ptp->lock, flags); + + ns += (((u64)hi) << HCLGE_PTP_SEC_H_OFFSET | lo) * NSEC_PER_SEC; + *ts = ns_to_timespec64(ns); + + return 0; +} + +static int hclge_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts) +{ + struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp); + unsigned long flags; + + spin_lock_irqsave(&hdev->ptp->lock, flags); + writel(ts->tv_nsec, hdev->ptp->io_base + HCLGE_PTP_TIME_NSEC_REG); + writel(ts->tv_sec >> HCLGE_PTP_SEC_H_OFFSET, + hdev->ptp->io_base + HCLGE_PTP_TIME_SEC_H_REG); + writel(ts->tv_sec & HCLGE_PTP_SEC_L_MASK, + hdev->ptp->io_base + HCLGE_PTP_TIME_SEC_L_REG); + /* synchronize the time of phc */ + writel(HCLGE_PTP_TIME_SYNC_EN, + hdev->ptp->io_base + HCLGE_PTP_TIME_SYNC_REG); + spin_unlock_irqrestore(&hdev->ptp->lock, flags); + + return 0; +} + +static int hclge_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct hclge_dev *hdev = hclge_ptp_get_hdev(ptp); + unsigned long flags; + bool is_neg = false; + u32 adj_val = 0; + + if (delta < 0) { + adj_val |= HCLGE_PTP_TIME_NSEC_NEG; + delta = -delta; + is_neg = true; + } + + if (delta > HCLGE_PTP_TIME_NSEC_MASK) { + struct timespec64 ts; + s64 ns; + + hclge_ptp_gettimex(ptp, &ts, NULL); + ns = timespec64_to_ns(&ts); + ns = is_neg ? ns - delta : ns + delta; + ts = ns_to_timespec64(ns); + return hclge_ptp_settime(ptp, &ts); + } + + adj_val |= delta & HCLGE_PTP_TIME_NSEC_MASK; + + spin_lock_irqsave(&hdev->ptp->lock, flags); + writel(adj_val, hdev->ptp->io_base + HCLGE_PTP_TIME_NSEC_REG); + writel(HCLGE_PTP_TIME_ADJ_EN, + hdev->ptp->io_base + HCLGE_PTP_TIME_ADJ_REG); + spin_unlock_irqrestore(&hdev->ptp->lock, flags); + + return 0; +} + +int hclge_ptp_get_cfg(struct hclge_dev *hdev, struct ifreq *ifr) +{ + if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) + return -EOPNOTSUPP; + + return copy_to_user(ifr->ifr_data, &hdev->ptp->ts_cfg, + sizeof(struct hwtstamp_config)) ? -EFAULT : 0; +} + +static int hclge_ptp_int_en(struct hclge_dev *hdev, bool en) +{ + struct hclge_ptp_int_cmd *req; + struct hclge_desc desc; + int ret; + + req = (struct hclge_ptp_int_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PTP_INT_EN, false); + req->int_en = en ? 1 : 0; + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to %s ptp interrupt, ret = %d\n", + en ? "enable" : "disable", ret); + + return ret; +} + +int hclge_ptp_cfg_qry(struct hclge_dev *hdev, u32 *cfg) +{ + struct hclge_ptp_cfg_cmd *req; + struct hclge_desc desc; + int ret; + + req = (struct hclge_ptp_cfg_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PTP_MODE_CFG, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to query ptp config, ret = %d\n", ret); + return ret; + } + + *cfg = le32_to_cpu(req->cfg); + + return 0; +} + +static int hclge_ptp_cfg(struct hclge_dev *hdev, u32 cfg) +{ + struct hclge_ptp_cfg_cmd *req; + struct hclge_desc desc; + int ret; + + req = (struct hclge_ptp_cfg_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PTP_MODE_CFG, false); + req->cfg = cpu_to_le32(cfg); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to config ptp, ret = %d\n", ret); + + return ret; +} + +static int hclge_ptp_set_tx_mode(struct hwtstamp_config *cfg, + unsigned long *flags, u32 *ptp_cfg) +{ + switch (cfg->tx_type) { + case HWTSTAMP_TX_OFF: + clear_bit(HCLGE_PTP_FLAG_TX_EN, flags); + break; + case HWTSTAMP_TX_ON: + set_bit(HCLGE_PTP_FLAG_TX_EN, flags); + *ptp_cfg |= HCLGE_PTP_TX_EN_B; + break; + default: + return -ERANGE; + } + + return 0; +} + +static int hclge_ptp_set_rx_mode(struct hwtstamp_config *cfg, + unsigned long *flags, u32 *ptp_cfg) +{ + int rx_filter = cfg->rx_filter; + + switch (cfg->rx_filter) { + case HWTSTAMP_FILTER_NONE: + clear_bit(HCLGE_PTP_FLAG_RX_EN, flags); + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + set_bit(HCLGE_PTP_FLAG_RX_EN, flags); + *ptp_cfg |= HCLGE_PTP_RX_EN_B; + *ptp_cfg |= HCLGE_PTP_UDP_FULL_TYPE << HCLGE_PTP_UDP_EN_SHIFT; + rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; + break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + set_bit(HCLGE_PTP_FLAG_RX_EN, flags); + *ptp_cfg |= HCLGE_PTP_RX_EN_B; + *ptp_cfg |= HCLGE_PTP_UDP_FULL_TYPE << HCLGE_PTP_UDP_EN_SHIFT; + *ptp_cfg |= HCLGE_PTP_MSG1_V2_DEFAULT << HCLGE_PTP_MSG1_SHIFT; + *ptp_cfg |= HCLGE_PTP_MSG0_V2_EVENT << HCLGE_PTP_MSG0_SHIFT; + *ptp_cfg |= HCLGE_PTP_MSG_TYPE_V2 << HCLGE_PTP_MSG_TYPE_SHIFT; + rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + break; + case HWTSTAMP_FILTER_ALL: + default: + return -ERANGE; + } + + cfg->rx_filter = rx_filter; + + return 0; +} + +static int hclge_ptp_set_ts_mode(struct hclge_dev *hdev, + struct hwtstamp_config *cfg) +{ + unsigned long flags = hdev->ptp->flags; + u32 ptp_cfg = 0; + int ret; + + if (test_bit(HCLGE_PTP_FLAG_EN, &hdev->ptp->flags)) + ptp_cfg |= HCLGE_PTP_EN_B; + + ret = hclge_ptp_set_tx_mode(cfg, &flags, &ptp_cfg); + if (ret) + return ret; + + ret = hclge_ptp_set_rx_mode(cfg, &flags, &ptp_cfg); + if (ret) + return ret; + + ret = hclge_ptp_cfg(hdev, ptp_cfg); + if (ret) + return ret; + + hdev->ptp->flags = flags; + hdev->ptp->ptp_cfg = ptp_cfg; + + return 0; +} + +int hclge_ptp_set_cfg(struct hclge_dev *hdev, struct ifreq *ifr) +{ + struct hwtstamp_config cfg; + int ret; + + if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) { + dev_err(&hdev->pdev->dev, "phc is unsupported\n"); + return -EOPNOTSUPP; + } + + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) + return -EFAULT; + + ret = hclge_ptp_set_ts_mode(hdev, &cfg); + if (ret) + return ret; + + hdev->ptp->ts_cfg = cfg; + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; +} + +int hclge_ptp_get_ts_info(struct hnae3_handle *handle, + struct ethtool_ts_info *info) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + + if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) { + dev_err(&hdev->pdev->dev, "phc is unsupported\n"); + return -EOPNOTSUPP; + } + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + if (hdev->ptp->clock) + info->phc_index = ptp_clock_index(hdev->ptp->clock); + else + info->phc_index = -1; + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ); + + info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); + + return 0; +} + +static int hclge_ptp_create_clock(struct hclge_dev *hdev) +{ +#define HCLGE_PTP_NAME_LEN 32 + + struct hclge_ptp *ptp; + + ptp = devm_kzalloc(&hdev->pdev->dev, sizeof(*ptp), GFP_KERNEL); + if (!ptp) + return -ENOMEM; + + ptp->hdev = hdev; + snprintf(ptp->info.name, HCLGE_PTP_NAME_LEN, "%s", + HCLGE_DRIVER_NAME); + ptp->info.owner = THIS_MODULE; + ptp->info.max_adj = HCLGE_PTP_CYCLE_ADJ_MAX; + ptp->info.n_ext_ts = 0; + ptp->info.pps = 0; + ptp->info.adjfreq = hclge_ptp_adjfreq; + ptp->info.adjtime = hclge_ptp_adjtime; + ptp->info.gettimex64 = hclge_ptp_gettimex; + ptp->info.settime64 = hclge_ptp_settime; + + ptp->info.n_alarm = 0; + ptp->clock = ptp_clock_register(&ptp->info, &hdev->pdev->dev); + if (IS_ERR(ptp->clock)) { + dev_err(&hdev->pdev->dev, + "%d failed to register ptp clock, ret = %ld\n", + ptp->info.n_alarm, PTR_ERR(ptp->clock)); + return -ENODEV; + } else if (!ptp->clock) { + dev_err(&hdev->pdev->dev, "failed to register ptp clock\n"); + return -ENODEV; + } + + spin_lock_init(&ptp->lock); + ptp->io_base = hdev->hw.io_base + HCLGE_PTP_REG_OFFSET; + ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE; + ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF; + hdev->ptp = ptp; + + return 0; +} + +static void hclge_ptp_destroy_clock(struct hclge_dev *hdev) +{ + ptp_clock_unregister(hdev->ptp->clock); + hdev->ptp->clock = NULL; + devm_kfree(&hdev->pdev->dev, hdev->ptp); + hdev->ptp = NULL; +} + +int hclge_ptp_init(struct hclge_dev *hdev) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + struct timespec64 ts; + int ret; + + if (!test_bit(HNAE3_DEV_SUPPORT_PTP_B, ae_dev->caps)) + return 0; + + if (!hdev->ptp) { + ret = hclge_ptp_create_clock(hdev); + if (ret) + return ret; + } + + ret = hclge_ptp_int_en(hdev, true); + if (ret) + goto out; + + set_bit(HCLGE_PTP_FLAG_EN, &hdev->ptp->flags); + ret = hclge_ptp_adjfreq(&hdev->ptp->info, 0); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to init freq, ret = %d\n", ret); + goto out; + } + + ret = hclge_ptp_set_ts_mode(hdev, &hdev->ptp->ts_cfg); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to init ts mode, ret = %d\n", ret); + goto out; + } + + ktime_get_real_ts64(&ts); + ret = hclge_ptp_settime(&hdev->ptp->info, &ts); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to init ts time, ret = %d\n", ret); + goto out; + } + + set_bit(HCLGE_STATE_PTP_EN, &hdev->state); + dev_info(&hdev->pdev->dev, "phc initializes ok!\n"); + + return 0; + +out: + hclge_ptp_destroy_clock(hdev); + + return ret; +} + +void hclge_ptp_uninit(struct hclge_dev *hdev) +{ + struct hclge_ptp *ptp = hdev->ptp; + + if (!ptp) + return; + + hclge_ptp_int_en(hdev, false); + clear_bit(HCLGE_STATE_PTP_EN, &hdev->state); + clear_bit(HCLGE_PTP_FLAG_EN, &ptp->flags); + ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE; + ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF; + + if (hclge_ptp_set_ts_mode(hdev, &ptp->ts_cfg)) + dev_err(&hdev->pdev->dev, "failed to disable phc\n"); + + if (ptp->tx_skb) { + struct sk_buff *skb = ptp->tx_skb; + + ptp->tx_skb = NULL; + dev_kfree_skb_any(skb); + } + + hclge_ptp_destroy_clock(hdev); +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h new file mode 100644 index 000000000000..b3ca7afdaaa6 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +// Copyright (c) 2021 Hisilicon Limited. + +#ifndef __HCLGE_PTP_H +#define __HCLGE_PTP_H + +#include <linux/ptp_clock_kernel.h> +#include <linux/net_tstamp.h> +#include <linux/types.h> + +#define HCLGE_PTP_REG_OFFSET 0x29000 + +#define HCLGE_PTP_TX_TS_SEQID_REG 0x0 +#define HCLGE_PTP_TX_TS_NSEC_REG 0x4 +#define HCLGE_PTP_TX_TS_NSEC_MASK GENMASK(29, 0) +#define HCLGE_PTP_TX_TS_SEC_L_REG 0x8 +#define HCLGE_PTP_TX_TS_SEC_H_REG 0xC +#define HCLGE_PTP_TX_TS_SEC_H_MASK GENMASK(15, 0) +#define HCLGE_PTP_TX_TS_CNT_REG 0x30 + +#define HCLGE_PTP_TIME_SEC_H_REG 0x50 +#define HCLGE_PTP_TIME_SEC_H_MASK GENMASK(15, 0) +#define HCLGE_PTP_TIME_SEC_L_REG 0x54 +#define HCLGE_PTP_TIME_NSEC_REG 0x58 +#define HCLGE_PTP_TIME_NSEC_MASK GENMASK(29, 0) +#define HCLGE_PTP_TIME_NSEC_NEG BIT(31) +#define HCLGE_PTP_TIME_SYNC_REG 0x5C +#define HCLGE_PTP_TIME_SYNC_EN BIT(0) +#define HCLGE_PTP_TIME_ADJ_REG 0x60 +#define HCLGE_PTP_TIME_ADJ_EN BIT(0) +#define HCLGE_PTP_CYCLE_QUO_REG 0x64 +#define HCLGE_PTP_CYCLE_DEN_REG 0x68 +#define HCLGE_PTP_CYCLE_NUM_REG 0x6C +#define HCLGE_PTP_CYCLE_CFG_REG 0x70 +#define HCLGE_PTP_CYCLE_ADJ_EN BIT(0) +#define HCLGE_PTP_CUR_TIME_SEC_H_REG 0x74 +#define HCLGE_PTP_CUR_TIME_SEC_L_REG 0x78 +#define HCLGE_PTP_CUR_TIME_NSEC_REG 0x7C + +#define HCLGE_PTP_CYCLE_ADJ_BASE 2 +#define HCLGE_PTP_CYCLE_ADJ_MAX 500000000 +#define HCLGE_PTP_CYCLE_ADJ_UNIT 100000000 +#define HCLGE_PTP_SEC_H_OFFSET 32u +#define HCLGE_PTP_SEC_L_MASK GENMASK(31, 0) + +#define HCLGE_PTP_FLAG_EN BIT(0) +#define HCLGE_PTP_FLAG_TX_EN BIT(1) +#define HCLGE_PTP_FLAG_RX_EN BIT(2) + +struct hclge_ptp { + struct hclge_dev *hdev; + struct ptp_clock *clock; + struct sk_buff *tx_skb; + unsigned long flags; + void __iomem *io_base; + struct ptp_clock_info info; + struct hwtstamp_config ts_cfg; + spinlock_t lock; /* protects ptp registers */ + u32 ptp_cfg; + u32 last_tx_seqid; + unsigned long tx_start; + unsigned long tx_cnt; + unsigned long tx_skipped; + unsigned long tx_cleaned; + unsigned long last_rx; + unsigned long rx_cnt; + unsigned long tx_timeout; +}; + +struct hclge_ptp_int_cmd { +#define HCLGE_PTP_INT_EN_B BIT(0) + + u8 int_en; + u8 rsvd[23]; +}; + +enum hclge_ptp_udp_type { + HCLGE_PTP_UDP_NOT_TYPE, + HCLGE_PTP_UDP_P13F_TYPE, + HCLGE_PTP_UDP_P140_TYPE, + HCLGE_PTP_UDP_FULL_TYPE, +}; + +enum hclge_ptp_msg_type { + HCLGE_PTP_MSG_TYPE_V2_L2, + HCLGE_PTP_MSG_TYPE_V2, + HCLGE_PTP_MSG_TYPE_V2_EVENT, +}; + +enum hclge_ptp_msg0_type { + HCLGE_PTP_MSG0_V2_DELAY_REQ = 1, + HCLGE_PTP_MSG0_V2_PDELAY_REQ, + HCLGE_PTP_MSG0_V2_DELAY_RESP, + HCLGE_PTP_MSG0_V2_EVENT = 0xF, +}; + +#define HCLGE_PTP_MSG1_V2_DEFAULT 1 + +struct hclge_ptp_cfg_cmd { +#define HCLGE_PTP_EN_B BIT(0) +#define HCLGE_PTP_TX_EN_B BIT(1) +#define HCLGE_PTP_RX_EN_B BIT(2) +#define HCLGE_PTP_UDP_EN_SHIFT 3 +#define HCLGE_PTP_UDP_EN_MASK GENMASK(4, 3) +#define HCLGE_PTP_MSG_TYPE_SHIFT 8 +#define HCLGE_PTP_MSG_TYPE_MASK GENMASK(9, 8) +#define HCLGE_PTP_MSG1_SHIFT 16 +#define HCLGE_PTP_MSG1_MASK GENMASK(19, 16) +#define HCLGE_PTP_MSG0_SHIFT 24 +#define HCLGE_PTP_MSG0_MASK GENMASK(27, 24) + + __le32 cfg; + u8 rsvd[20]; +}; + +static inline struct hclge_dev *hclge_ptp_get_hdev(struct ptp_clock_info *info) +{ + struct hclge_ptp *ptp = container_of(info, struct hclge_ptp, info); + + return ptp->hdev; +} + +bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb); +void hclge_ptp_clean_tx_hwts(struct hclge_dev *dev); +void hclge_ptp_get_rx_hwts(struct hnae3_handle *handle, struct sk_buff *skb, + u32 nsec, u32 sec); +int hclge_ptp_get_cfg(struct hclge_dev *hdev, struct ifreq *ifr); +int hclge_ptp_set_cfg(struct hclge_dev *hdev, struct ifreq *ifr); +int hclge_ptp_init(struct hclge_dev *hdev); +void hclge_ptp_uninit(struct hclge_dev *hdev); +int hclge_ptp_get_ts_info(struct hnae3_handle *handle, + struct ethtool_ts_info *info); +int hclge_ptp_cfg_qry(struct hclge_dev *hdev, u32 *cfg); +#endif
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit b34c157f0cdd0b9e52c002288ff77b1a553dd438 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Add a debugfs interface for dumping ptp information, which is helpful for debugging.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Yufeng Mo moyufeng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 13 ++++- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 55 +++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 89f45384ca13..dbc9b1316272 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -275,6 +275,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_MAC_MC, HNAE3_DBG_CMD_MNG_TBL, HNAE3_DBG_CMD_LOOPBACK, + HNAE3_DBG_CMD_PTP_INFO, HNAE3_DBG_CMD_INTERRUPT_INFO, HNAE3_DBG_CMD_RESET_INFO, HNAE3_DBG_CMD_IMP_INFO, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index a0edca848392..c512a63c423b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -316,6 +316,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "ptp_info", + .cmd = HNAE3_DBG_CMD_PTP_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { @@ -1059,8 +1066,10 @@ int hns3_dbg_init(struct hnae3_handle *handle) handle->hnae3_dbgfs);
for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { - if (hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES && - ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) + if ((hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES && + ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) || + (hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_PTP_INFO && + !test_bit(HNAE3_DEV_SUPPORT_PTP_B, ae_dev->caps))) continue;
if (!hns3_dbg_cmd[i].init) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 0d433a5ff807..6fc50d09b9db 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -2173,6 +2173,57 @@ static int hclge_dbg_dump_vlan_config(struct hclge_dev *hdev, char *buf, return hclge_dbg_dump_vlan_offload_config(hdev, buf, len, &pos); }
+static int hclge_dbg_dump_ptp_info(struct hclge_dev *hdev, char *buf, int len) +{ + struct hclge_ptp *ptp = hdev->ptp; + u32 sw_cfg = ptp->ptp_cfg; + unsigned int tx_start; + unsigned int last_rx; + int pos = 0; + u32 hw_cfg; + int ret; + + pos += scnprintf(buf + pos, len - pos, "phc %s's debug info:\n", + ptp->info.name); + pos += scnprintf(buf + pos, len - pos, "ptp enable: %s\n", + test_bit(HCLGE_PTP_FLAG_EN, &ptp->flags) ? + "yes" : "no"); + pos += scnprintf(buf + pos, len - pos, "ptp tx enable: %s\n", + test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) ? + "yes" : "no"); + pos += scnprintf(buf + pos, len - pos, "ptp rx enable: %s\n", + test_bit(HCLGE_PTP_FLAG_RX_EN, &ptp->flags) ? + "yes" : "no"); + + last_rx = jiffies_to_msecs(ptp->last_rx); + pos += scnprintf(buf + pos, len - pos, "last rx time: %lu.%lu\n", + last_rx / MSEC_PER_SEC, last_rx % MSEC_PER_SEC); + pos += scnprintf(buf + pos, len - pos, "rx count: %lu\n", ptp->rx_cnt); + + tx_start = jiffies_to_msecs(ptp->tx_start); + pos += scnprintf(buf + pos, len - pos, "last tx start time: %lu.%lu\n", + tx_start / MSEC_PER_SEC, tx_start % MSEC_PER_SEC); + pos += scnprintf(buf + pos, len - pos, "tx count: %lu\n", ptp->tx_cnt); + pos += scnprintf(buf + pos, len - pos, "tx skipped count: %lu\n", + ptp->tx_skipped); + pos += scnprintf(buf + pos, len - pos, "tx timeout count: %lu\n", + ptp->tx_timeout); + pos += scnprintf(buf + pos, len - pos, "last tx seqid: %u\n", + ptp->last_tx_seqid); + + ret = hclge_ptp_cfg_qry(hdev, &hw_cfg); + if (ret) + return ret; + + pos += scnprintf(buf + pos, len - pos, "sw_cfg: %#x, hw_cfg: %#x\n", + sw_cfg, hw_cfg); + + pos += scnprintf(buf + pos, len - pos, "tx type: %d, rx filter: %d\n", + ptp->ts_cfg.tx_type, ptp->ts_cfg.rx_filter); + + return 0; +} + static int hclge_dbg_dump_mac_uc(struct hclge_dev *hdev, char *buf, int len) { hclge_dbg_dump_mac_list(hdev, buf, len, true); @@ -2244,6 +2295,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_LOOPBACK, .dbg_dump = hclge_dbg_dump_loopback, }, + { + .cmd = HNAE3_DBG_CMD_PTP_INFO, + .dbg_dump = hclge_dbg_dump_ptp_info, + }, { .cmd = HNAE3_DBG_CMD_INTERRUPT_INFO, .dbg_dump = hclge_dbg_dump_interrupt,
From: Dan Carpenter dan.carpenter@oracle.com
mainline inclusion from mainline-master commit 956c3ae411b2746c5018e0454909eb8c662b31ef category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
These flags are used to set and test bits like this:
if (!test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) ||
The issue is that test_bit() takes a bit number like 1, but we are passing BIT(1) instead and it's testing BIT(BIT(1)). This does not cause a problem because it is always done consistently and the bit values are very small.
Fixes: 0bf5eb788512 ("net: hns3: add support for PTP") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h index b3ca7afdaaa6..5a202b775471 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h @@ -43,9 +43,9 @@ #define HCLGE_PTP_SEC_H_OFFSET 32u #define HCLGE_PTP_SEC_L_MASK GENMASK(31, 0)
-#define HCLGE_PTP_FLAG_EN BIT(0) -#define HCLGE_PTP_FLAG_TX_EN BIT(1) -#define HCLGE_PTP_FLAG_RX_EN BIT(2) +#define HCLGE_PTP_FLAG_EN 0 +#define HCLGE_PTP_FLAG_TX_EN 1 +#define HCLGE_PTP_FLAG_RX_EN 2
struct hclge_ptp { struct hclge_dev *hdev;
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit 26f1ccdf609a9fb087f49a3782fdc2ade23cde82 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
desc_cb is used to store mapping and freeing info for the corresponding desc, which is used in the cleaning process. There will be more desc_cb type coming up when supporting the tx bounce buffer, change desc_cb type to bit-wise value in order to reduce the desc_cb type checking operation in the data path.
Also move the desc_cb type definition to hns3_enet.h because it is only used in hns3_enet.c, and declare a local variable desc_cb in hns3_clear_desc() to reduce lines of code.
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 7 ---- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 40 +++++++++---------- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 7 ++++ 3 files changed, 25 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index dbc9b1316272..13e2952c5da0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -158,13 +158,6 @@ enum HNAE3_PF_CAP_BITS { #define ring_ptr_move_bw(ring, p) \ ((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
-enum hns_desc_type { - DESC_TYPE_UNKNOWN, - DESC_TYPE_SKB, - DESC_TYPE_FRAGLIST_SKB, - DESC_TYPE_PAGE, -}; - struct hnae3_handle;
struct hnae3_queue { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9a45f3cde6a2..f03a7a962eb0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1413,7 +1413,7 @@ static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, }
static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, - unsigned int size, enum hns_desc_type type) + unsigned int size, unsigned int type) { #define HNS3_LIKELY_BD_NUM 1
@@ -1425,8 +1425,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, int k, sizeoflast; dma_addr_t dma;
- if (type == DESC_TYPE_FRAGLIST_SKB || - type == DESC_TYPE_SKB) { + if (type & (DESC_TYPE_FRAGLIST_SKB | DESC_TYPE_SKB)) { struct sk_buff *skb = (struct sk_buff *)priv;
dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); @@ -1704,6 +1703,7 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
for (i = 0; i < ring->desc_num; i++) { struct hns3_desc *desc = &ring->desc[ring->next_to_use]; + struct hns3_desc_cb *desc_cb;
memset(desc, 0, sizeof(*desc));
@@ -1714,31 +1714,27 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) /* rollback one */ ring_ptr_move_bw(ring, next_to_use);
- if (!ring->desc_cb[ring->next_to_use].dma) + desc_cb = &ring->desc_cb[ring->next_to_use]; + + if (!desc_cb->dma) continue;
/* unmap the descriptor dma address */ - if (ring->desc_cb[ring->next_to_use].type == DESC_TYPE_SKB || - ring->desc_cb[ring->next_to_use].type == - DESC_TYPE_FRAGLIST_SKB) - dma_unmap_single(dev, - ring->desc_cb[ring->next_to_use].dma, - ring->desc_cb[ring->next_to_use].length, - DMA_TO_DEVICE); - else if (ring->desc_cb[ring->next_to_use].length) - dma_unmap_page(dev, - ring->desc_cb[ring->next_to_use].dma, - ring->desc_cb[ring->next_to_use].length, + if (desc_cb->type & (DESC_TYPE_SKB | DESC_TYPE_FRAGLIST_SKB)) + dma_unmap_single(dev, desc_cb->dma, desc_cb->length, + DMA_TO_DEVICE); + else if (desc_cb->length) + dma_unmap_page(dev, desc_cb->dma, desc_cb->length, DMA_TO_DEVICE);
- ring->desc_cb[ring->next_to_use].length = 0; - ring->desc_cb[ring->next_to_use].dma = 0; - ring->desc_cb[ring->next_to_use].type = DESC_TYPE_UNKNOWN; + desc_cb->length = 0; + desc_cb->dma = 0; + desc_cb->type = DESC_TYPE_UNKNOWN; } }
static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, - struct sk_buff *skb, enum hns_desc_type type) + struct sk_buff *skb, unsigned int type) { unsigned int size = skb_headlen(skb); struct sk_buff *frag_skb; @@ -2859,7 +2855,7 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, static void hns3_free_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb, int budget) { - if (cb->type == DESC_TYPE_SKB) + if (cb->type & DESC_TYPE_SKB) napi_consume_skb(cb->priv, budget); else if (!HNAE3_IS_TX_RING(ring) && cb->pagecnt_bias) __page_frag_cache_drain(cb->priv, cb->pagecnt_bias); @@ -2880,7 +2876,7 @@ static int hns3_map_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb) static void hns3_unmap_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb) { - if (cb->type == DESC_TYPE_SKB || cb->type == DESC_TYPE_FRAGLIST_SKB) + if (cb->type & (DESC_TYPE_SKB | DESC_TYPE_FRAGLIST_SKB)) dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length, ring_to_dma_dir(ring)); else if (cb->length) @@ -3037,7 +3033,7 @@ static bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring,
desc_cb = &ring->desc_cb[ntc];
- if (desc_cb->type == DESC_TYPE_SKB) { + if (desc_cb->type & DESC_TYPE_SKB) { (*pkts)++; (*bytes) += desc_cb->send_bytes; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 79821c7bdc16..9d18b9430b54 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -299,6 +299,13 @@ struct __packed hns3_desc { }; };
+enum hns3_desc_type { + DESC_TYPE_UNKNOWN = 0, + DESC_TYPE_SKB = 1 << 0, + DESC_TYPE_FRAGLIST_SKB = 1 << 1, + DESC_TYPE_PAGE = 1 << 2, +}; + struct hns3_desc_cb { dma_addr_t dma; /* dma address of this desc */ void *buf; /* cpu addr for a desc */
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit 8677d78c3d860c156ccd335e2b97728298c2cbb1 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Factor out hns3_fill_desc() so that it can be reused in the tx bounce supporting.
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 87 ++++++++++--------- 1 file changed, 48 insertions(+), 39 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index f03a7a962eb0..6fa1ed5c4098 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1412,39 +1412,14 @@ static int hns3_fill_skb_desc(struct hns3_enet_ring *ring, return 0; }
-static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, - unsigned int size, unsigned int type) +static int hns3_fill_desc(struct hns3_enet_ring *ring, dma_addr_t dma, + unsigned int size) { #define HNS3_LIKELY_BD_NUM 1
- struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; struct hns3_desc *desc = &ring->desc[ring->next_to_use]; - struct device *dev = ring_to_dev(ring); - skb_frag_t *frag; unsigned int frag_buf_num; int k, sizeoflast; - dma_addr_t dma; - - if (type & (DESC_TYPE_FRAGLIST_SKB | DESC_TYPE_SKB)) { - struct sk_buff *skb = (struct sk_buff *)priv; - - dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); - } else { - frag = (skb_frag_t *)priv; - dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); - } - - if (unlikely(dma_mapping_error(dev, dma))) { - u64_stats_update_begin(&ring->syncp); - ring->stats.sw_err_cnt++; - u64_stats_update_end(&ring->syncp); - return -ENOMEM; - } - - desc_cb->priv = priv; - desc_cb->length = size; - desc_cb->dma = dma; - desc_cb->type = type;
if (likely(size <= HNS3_MAX_BD_SIZE)) { desc->addr = cpu_to_le64(dma); @@ -1480,6 +1455,47 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, return frag_buf_num; }
+static int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv, + unsigned int type) +{ + struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; + struct device *dev = ring_to_dev(ring); + unsigned int size; + dma_addr_t dma; + + if (type & (DESC_TYPE_FRAGLIST_SKB | DESC_TYPE_SKB)) { + struct sk_buff *skb = (struct sk_buff *)priv; + + size = skb_headlen(skb); + if (!size) + return 0; + + dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); + } else { + skb_frag_t *frag = (skb_frag_t *)priv; + + size = skb_frag_size(frag); + if (!size) + return 0; + + dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); + } + + if (unlikely(dma_mapping_error(dev, dma))) { + u64_stats_update_begin(&ring->syncp); + ring->stats.sw_err_cnt++; + u64_stats_update_end(&ring->syncp); + return -ENOMEM; + } + + desc_cb->priv = priv; + desc_cb->length = size; + desc_cb->dma = dma; + desc_cb->type = type; + + return hns3_fill_desc(ring, dma, size); +} + static unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size, unsigned int bd_num) { @@ -1736,26 +1752,19 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring, struct sk_buff *skb, unsigned int type) { - unsigned int size = skb_headlen(skb); struct sk_buff *frag_skb; int i, ret, bd_num = 0;
- if (size) { - ret = hns3_fill_desc(ring, skb, size, type); - if (unlikely(ret < 0)) - return ret; + ret = hns3_map_and_fill_desc(ring, skb, type); + if (unlikely(ret < 0)) + return ret;
- bd_num += ret; - } + bd_num += ret;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- size = skb_frag_size(frag); - if (!size) - continue; - - ret = hns3_fill_desc(ring, frag, size, DESC_TYPE_PAGE); + ret = hns3_map_and_fill_desc(ring, frag, DESC_TYPE_PAGE); if (unlikely(ret < 0)) return ret;
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit 907676b130711fd1f627824559e92259db2061d1 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
when the packet or frag size is small, it causes both security and performance issue. As dma can't map sub-page, this means some extra kernel data is visible to devices. On the other hand, the overhead of dma map and unmap is huge when IOMMU is on.
So add a queue based tx shared bounce buffer to memcpy the small packet when the len of the xmitted skb is below tx_copybreak. Add tx_spare_buf_size module param to set the size of tx spare buffer, and add set/get_tunable to set or query the tx_copybreak.
The throughtput improves from 30 Gbps to 90+ Gbps when running 16 netperf threads with 32KB UDP message size when IOMMU is in the strict mode(tx_copybreak = 2000 and mtu = 1500).
Suggested-by: Barry Song song.bao.hua@hisilicon.com Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 52 ++++ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 289 +++++++++++++++++- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 43 ++- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 51 ++++ 4 files changed, 420 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index c512a63c423b..a24a75c47cad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -392,6 +392,56 @@ static void hns3_dbg_fill_content(char *content, u16 len, *pos++ = '\0'; }
+static const struct hns3_dbg_item tx_spare_info_items[] = { + { "QUEUE_ID", 2 }, + { "COPYBREAK", 2 }, + { "LEN", 7 }, + { "NTU", 4 }, + { "NTC", 4 }, + { "LTC", 4 }, + { "DMA", 17 }, +}; + +static void hns3_dbg_tx_spare_info(struct hns3_enet_ring *ring, char *buf, + int len, u32 ring_num, int *pos) +{ + char data_str[ARRAY_SIZE(tx_spare_info_items)][HNS3_DBG_DATA_STR_LEN]; + struct hns3_tx_spare *tx_spare = ring->tx_spare; + char *result[ARRAY_SIZE(tx_spare_info_items)]; + char content[HNS3_DBG_INFO_LEN]; + u32 i, j; + + if (!tx_spare) { + *pos += scnprintf(buf + *pos, len - *pos, + "tx spare buffer is not enabled\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(tx_spare_info_items); i++) + result[i] = &data_str[i][0]; + + *pos += scnprintf(buf + *pos, len - *pos, "tx spare buffer info\n"); + hns3_dbg_fill_content(content, sizeof(content), tx_spare_info_items, + NULL, ARRAY_SIZE(tx_spare_info_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + + for (i = 0; i < ring_num; i++) { + j = 0; + sprintf(result[j++], "%8u", i); + sprintf(result[j++], "%9u", ring->tx_copybreak); + sprintf(result[j++], "%3u", tx_spare->len); + sprintf(result[j++], "%3u", tx_spare->next_to_use); + sprintf(result[j++], "%3u", tx_spare->next_to_clean); + sprintf(result[j++], "%3u", tx_spare->last_to_clean); + sprintf(result[j++], "%pad", &tx_spare->dma); + hns3_dbg_fill_content(content, sizeof(content), + tx_spare_info_items, + (const char **)result, + ARRAY_SIZE(tx_spare_info_items)); + *pos += scnprintf(buf + *pos, len - *pos, "%s", content); + } +} + static const struct hns3_dbg_item rx_queue_info_items[] = { { "QUEUE_ID", 2 }, { "BD_NUM", 2 }, @@ -593,6 +643,8 @@ static int hns3_dbg_tx_queue_info(struct hnae3_handle *h, pos += scnprintf(buf + pos, len - pos, "%s", content); }
+ hns3_dbg_tx_spare_info(ring, buf, len, h->kinfo.num_tqps, &pos); + return 0; }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 6fa1ed5c4098..e5466daac1c4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -53,6 +53,10 @@ static int debug = -1; module_param(debug, int, 0); MODULE_PARM_DESC(debug, " Network interface message level setting");
+static unsigned int tx_spare_buf_size; +module_param(tx_spare_buf_size, uint, 0400); +MODULE_PARM_DESC(tx_spare_buf_size, "Size used to allocate tx spare buffer"); + #define DEFAULT_MSG_LEVEL (NETIF_MSG_PROBE | NETIF_MSG_LINK | \ NETIF_MSG_IFDOWN | NETIF_MSG_IFUP)
@@ -941,6 +945,177 @@ void hns3_request_update_promisc_mode(struct hnae3_handle *handle) ops->request_update_promisc_mode(handle); }
+static u32 hns3_tx_spare_space(struct hns3_enet_ring *ring) +{ + struct hns3_tx_spare *tx_spare = ring->tx_spare; + u32 ntc, ntu; + + /* This smp_load_acquire() pairs with smp_store_release() in + * hns3_tx_spare_update() called in tx desc cleaning process. + */ + ntc = smp_load_acquire(&tx_spare->last_to_clean); + ntu = tx_spare->next_to_use; + + if (ntc > ntu) + return ntc - ntu - 1; + + /* The free tx buffer is divided into two part, so pick the + * larger one. + */ + return (ntc > (tx_spare->len - ntu) ? ntc : + (tx_spare->len - ntu)) - 1; +} + +static void hns3_tx_spare_update(struct hns3_enet_ring *ring) +{ + struct hns3_tx_spare *tx_spare = ring->tx_spare; + + if (!tx_spare || + tx_spare->last_to_clean == tx_spare->next_to_clean) + return; + + /* This smp_store_release() pairs with smp_load_acquire() in + * hns3_tx_spare_space() called in xmit process. + */ + smp_store_release(&tx_spare->last_to_clean, + tx_spare->next_to_clean); +} + +static bool hns3_can_use_tx_bounce(struct hns3_enet_ring *ring, + struct sk_buff *skb, + u32 space) +{ + u32 len = skb->len <= ring->tx_copybreak ? skb->len : + skb_headlen(skb); + + if (len > ring->tx_copybreak) + return false; + + if (ALIGN(len, dma_get_cache_alignment()) > space) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_spare_full++; + u64_stats_update_end(&ring->syncp); + return false; + } + + return true; +} + +static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) +{ + struct hns3_tx_spare *tx_spare; + struct page *page; + dma_addr_t dma; + int order; + + if (!tx_spare_buf_size) + return; + + order = get_order(tx_spare_buf_size); + tx_spare = devm_kzalloc(ring_to_dev(ring), sizeof(*tx_spare), + GFP_KERNEL); + if (!tx_spare) { + /* The driver still work without the tx spare buffer */ + dev_warn(ring_to_dev(ring), "failed to allocate hns3_tx_spare\n"); + return; + } + + page = alloc_pages_node(dev_to_node(ring_to_dev(ring)), + GFP_KERNEL, order); + if (!page) { + dev_warn(ring_to_dev(ring), "failed to allocate tx spare pages\n"); + devm_kfree(ring_to_dev(ring), tx_spare); + return; + } + + dma = dma_map_page(ring_to_dev(ring), page, 0, + PAGE_SIZE << order, DMA_TO_DEVICE); + if (dma_mapping_error(ring_to_dev(ring), dma)) { + dev_warn(ring_to_dev(ring), "failed to map pages for tx spare\n"); + put_page(page); + devm_kfree(ring_to_dev(ring), tx_spare); + return; + } + + tx_spare->dma = dma; + tx_spare->buf = page_address(page); + tx_spare->len = PAGE_SIZE << order; + ring->tx_spare = tx_spare; +} + +/* Use hns3_tx_spare_space() to make sure there is enough buffer + * before calling below function to allocate tx buffer. + */ +static void *hns3_tx_spare_alloc(struct hns3_enet_ring *ring, + unsigned int size, dma_addr_t *dma, + u32 *cb_len) +{ + struct hns3_tx_spare *tx_spare = ring->tx_spare; + u32 ntu = tx_spare->next_to_use; + + size = ALIGN(size, dma_get_cache_alignment()); + *cb_len = size; + + /* Tx spare buffer wraps back here because the end of + * freed tx buffer is not enough. + */ + if (ntu + size > tx_spare->len) { + *cb_len += (tx_spare->len - ntu); + ntu = 0; + } + + tx_spare->next_to_use = ntu + size; + if (tx_spare->next_to_use == tx_spare->len) + tx_spare->next_to_use = 0; + + *dma = tx_spare->dma + ntu; + + return tx_spare->buf + ntu; +} + +static void hns3_tx_spare_rollback(struct hns3_enet_ring *ring, u32 len) +{ + struct hns3_tx_spare *tx_spare = ring->tx_spare; + + if (len > tx_spare->next_to_use) { + len -= tx_spare->next_to_use; + tx_spare->next_to_use = tx_spare->len - len; + } else { + tx_spare->next_to_use -= len; + } +} + +static void hns3_tx_spare_reclaim_cb(struct hns3_enet_ring *ring, + struct hns3_desc_cb *cb) +{ + struct hns3_tx_spare *tx_spare = ring->tx_spare; + u32 ntc = tx_spare->next_to_clean; + u32 len = cb->length; + + tx_spare->next_to_clean += len; + + if (tx_spare->next_to_clean >= tx_spare->len) { + tx_spare->next_to_clean -= tx_spare->len; + + if (tx_spare->next_to_clean) { + ntc = 0; + len = tx_spare->next_to_clean; + } + } + + /* This tx spare buffer is only really reclaimed after calling + * hns3_tx_spare_update(), so it is still safe to use the info in + * the tx buffer to do the dma sync after tx_spare->next_to_clean + * is moved forword. + */ + if (cb->type & (DESC_TYPE_BOUNCE_HEAD | DESC_TYPE_BOUNCE_ALL)) { + dma_addr_t dma = tx_spare->dma + ntc; + + dma_sync_single_for_cpu(ring_to_dev(ring), dma, len, + DMA_TO_DEVICE); + } +} + static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, u16 *mss, u32 *type_cs_vlan_tso, u32 *send_bytes) { @@ -1471,6 +1646,11 @@ static int hns3_map_and_fill_desc(struct hns3_enet_ring *ring, void *priv, return 0;
dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); + } else if (type & DESC_TYPE_BOUNCE_HEAD) { + /* Head data has been filled in hns3_handle_tx_bounce(), + * just return 0 here. + */ + return 0; } else { skb_frag_t *frag = (skb_frag_t *)priv;
@@ -1739,6 +1919,9 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) if (desc_cb->type & (DESC_TYPE_SKB | DESC_TYPE_FRAGLIST_SKB)) dma_unmap_single(dev, desc_cb->dma, desc_cb->length, DMA_TO_DEVICE); + else if (desc_cb->type & + (DESC_TYPE_BOUNCE_HEAD | DESC_TYPE_BOUNCE_ALL)) + hns3_tx_spare_rollback(ring, desc_cb->length); else if (desc_cb->length) dma_unmap_page(dev, desc_cb->dma, desc_cb->length, DMA_TO_DEVICE); @@ -1816,6 +1999,79 @@ static void hns3_tsyn(struct net_device *netdev, struct sk_buff *skb, desc->tx.bdtp_fe_sc_vld_ra_ri |= cpu_to_le16(BIT(HNS3_TXD_TSYN_B)); }
+static int hns3_handle_tx_bounce(struct hns3_enet_ring *ring, + struct sk_buff *skb) +{ + struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; + unsigned int type = DESC_TYPE_BOUNCE_HEAD; + unsigned int size = skb_headlen(skb); + dma_addr_t dma; + int bd_num = 0; + u32 cb_len; + void *buf; + int ret; + + if (skb->len <= ring->tx_copybreak) { + size = skb->len; + type = DESC_TYPE_BOUNCE_ALL; + } + + /* hns3_can_use_tx_bounce() is called to ensure the below + * function can always return the tx buffer. + */ + buf = hns3_tx_spare_alloc(ring, size, &dma, &cb_len); + + ret = skb_copy_bits(skb, 0, buf, size); + if (unlikely(ret < 0)) { + hns3_tx_spare_rollback(ring, cb_len); + u64_stats_update_begin(&ring->syncp); + ring->stats.copy_bits_err++; + u64_stats_update_end(&ring->syncp); + return ret; + } + + desc_cb->priv = skb; + desc_cb->length = cb_len; + desc_cb->dma = dma; + desc_cb->type = type; + + bd_num += hns3_fill_desc(ring, dma, size); + + if (type == DESC_TYPE_BOUNCE_HEAD) { + ret = hns3_fill_skb_to_desc(ring, skb, + DESC_TYPE_BOUNCE_HEAD); + if (unlikely(ret < 0)) + return ret; + + bd_num += ret; + } + + dma_sync_single_for_device(ring_to_dev(ring), dma, size, + DMA_TO_DEVICE); + + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_bounce++; + u64_stats_update_end(&ring->syncp); + return bd_num; +} + +static int hns3_handle_desc_filling(struct hns3_enet_ring *ring, + struct sk_buff *skb) +{ + u32 space; + + if (!ring->tx_spare) + goto out; + + space = hns3_tx_spare_space(ring); + + if (hns3_can_use_tx_bounce(ring, skb, space)) + return hns3_handle_tx_bounce(ring, skb); + +out: + return hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB); +} + netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -1862,7 +2118,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) * zero, which is unlikely, and 'ret > 0' means how many tx desc * need to be notified to the hw. */ - ret = hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB); + ret = hns3_handle_desc_filling(ring, skb); if (unlikely(ret <= 0)) goto fill_err;
@@ -2064,6 +2320,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_drop += ring->stats.tx_tso_err; tx_drop += ring->stats.over_max_recursion; tx_drop += ring->stats.hw_limitation; + tx_drop += ring->stats.copy_bits_err; tx_errors += ring->stats.sw_err_cnt; tx_errors += ring->stats.tx_vlan_err; tx_errors += ring->stats.tx_l4_proto_err; @@ -2071,6 +2328,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_errors += ring->stats.tx_tso_err; tx_errors += ring->stats.over_max_recursion; tx_errors += ring->stats.hw_limitation; + tx_errors += ring->stats.copy_bits_err; } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
/* fetch the rx stats */ @@ -2864,7 +3122,8 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, static void hns3_free_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb, int budget) { - if (cb->type & DESC_TYPE_SKB) + if (cb->type & (DESC_TYPE_SKB | DESC_TYPE_BOUNCE_HEAD | + DESC_TYPE_BOUNCE_ALL)) napi_consume_skb(cb->priv, budget); else if (!HNAE3_IS_TX_RING(ring) && cb->pagecnt_bias) __page_frag_cache_drain(cb->priv, cb->pagecnt_bias); @@ -2888,9 +3147,11 @@ static void hns3_unmap_buffer(struct hns3_enet_ring *ring, if (cb->type & (DESC_TYPE_SKB | DESC_TYPE_FRAGLIST_SKB)) dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length, ring_to_dma_dir(ring)); - else if (cb->length) + else if ((cb->type & DESC_TYPE_PAGE) && cb->length) dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length, ring_to_dma_dir(ring)); + else if (cb->type & (DESC_TYPE_BOUNCE_ALL | DESC_TYPE_BOUNCE_HEAD)) + hns3_tx_spare_reclaim_cb(ring, cb); }
static void hns3_buffer_detach(struct hns3_enet_ring *ring, int i) @@ -3042,7 +3303,8 @@ static bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring,
desc_cb = &ring->desc_cb[ntc];
- if (desc_cb->type & DESC_TYPE_SKB) { + if (desc_cb->type & (DESC_TYPE_SKB | DESC_TYPE_BOUNCE_ALL | + DESC_TYPE_BOUNCE_HEAD)) { (*pkts)++; (*bytes) += desc_cb->send_bytes; } @@ -3065,6 +3327,9 @@ static bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring, * ring_space called by hns3_nic_net_xmit. */ smp_store_release(&ring->next_to_clean, ntc); + + hns3_tx_spare_update(ring); + return true; }
@@ -4245,6 +4510,8 @@ static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, ring = &priv->ring[q->tqp_index]; desc_num = priv->ae_handle->kinfo.num_tx_desc; ring->queue_index = q->tqp_index; + ring->tx_copybreak = priv->tx_copybreak; + ring->last_to_use = 0; } else { ring = &priv->ring[q->tqp_index + queue_num]; desc_num = priv->ae_handle->kinfo.num_rx_desc; @@ -4262,7 +4529,6 @@ static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, ring->desc_num = desc_num; ring->next_to_use = 0; ring->next_to_clean = 0; - ring->last_to_use = 0; }
static void hns3_queue_to_ring(struct hnae3_queue *tqp, @@ -4322,6 +4588,8 @@ static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring) ret = hns3_alloc_ring_buffers(ring); if (ret) goto out_with_desc; + } else { + hns3_init_tx_spare_buffer(ring); }
return 0; @@ -4344,9 +4612,18 @@ void hns3_fini_ring(struct hns3_enet_ring *ring) ring->next_to_use = 0; ring->last_to_use = 0; ring->pending_buf = 0; - if (ring->skb) { + if (!HNAE3_IS_TX_RING(ring) && ring->skb) { dev_kfree_skb_any(ring->skb); ring->skb = NULL; + } else if (HNAE3_IS_TX_RING(ring) && ring->tx_spare) { + struct hns3_tx_spare *tx_spare = ring->tx_spare; + + dma_unmap_page(ring_to_dev(ring), tx_spare->dma, tx_spare->len, + DMA_TO_DEVICE); + free_pages((unsigned long)tx_spare->buf, + get_order(tx_spare->len)); + devm_kfree(ring_to_dev(ring), tx_spare); + ring->tx_spare = NULL; } }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 9d18b9430b54..8d147c1dab2c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -304,6 +304,8 @@ enum hns3_desc_type { DESC_TYPE_SKB = 1 << 0, DESC_TYPE_FRAGLIST_SKB = 1 << 1, DESC_TYPE_PAGE = 1 << 2, + DESC_TYPE_BOUNCE_ALL = 1 << 3, + DESC_TYPE_BOUNCE_HEAD = 1 << 4, };
struct hns3_desc_cb { @@ -405,6 +407,9 @@ struct ring_stats { u64 tx_tso_err; u64 over_max_recursion; u64 hw_limitation; + u64 tx_bounce; + u64 tx_spare_full; + u64 copy_bits_err; }; struct { u64 rx_pkts; @@ -423,6 +428,15 @@ struct ring_stats { }; };
+struct hns3_tx_spare { + dma_addr_t dma; + void *buf; + u32 next_to_use; + u32 next_to_clean; + u32 last_to_clean; + u32 len; +}; + struct hns3_enet_ring { struct hns3_desc *desc; /* dma map address space */ struct hns3_desc_cb *desc_cb; @@ -445,18 +459,28 @@ struct hns3_enet_ring { * next_to_use */ int next_to_clean; - union { - int last_to_use; /* last idx used by xmit */ - u32 pull_len; /* memcpy len for current rx packet */ - }; - u32 frag_num; - void *va; /* first buffer address for current packet */ - u32 flag; /* ring attribute */
int pending_buf; - struct sk_buff *skb; - struct sk_buff *tail_skb; + union { + /* for Tx ring */ + struct { + u32 fd_qb_tx_sample; + int last_to_use; /* last idx used by xmit */ + u32 tx_copybreak; + struct hns3_tx_spare *tx_spare; + }; + + /* for Rx ring */ + struct { + u32 pull_len; /* memcpy len for current rx packet */ + u32 frag_num; + /* first buffer address for current packet */ + unsigned char *va; + struct sk_buff *skb; + struct sk_buff *tail_skb; + }; + }; } ____cacheline_internodealigned_in_smp;
enum hns3_flow_level_range { @@ -540,6 +564,7 @@ struct hns3_nic_priv {
struct hns3_enet_coalesce tx_coal; struct hns3_enet_coalesce rx_coal; + u32 tx_copybreak; };
union l3_hdr_info { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index acef5435d7b7..f306de16d73f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -46,6 +46,9 @@ static const struct hns3_stats hns3_txq_stats[] = { HNS3_TQP_STAT("tso_err", tx_tso_err), HNS3_TQP_STAT("over_max_recursion", over_max_recursion), HNS3_TQP_STAT("hw_limitation", hw_limitation), + HNS3_TQP_STAT("bounce", tx_bounce), + HNS3_TQP_STAT("spare_full", tx_spare_full), + HNS3_TQP_STAT("copy_bits_err", copy_bits_err), };
#define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats) @@ -1592,6 +1595,50 @@ static int hns3_set_priv_flags(struct net_device *netdev, u32 pflags) return 0; }
+static int hns3_get_tunable(struct net_device *netdev, + const struct ethtool_tunable *tuna, + void *data) +{ + struct hns3_nic_priv *priv = netdev_priv(netdev); + int ret = 0; + + switch (tuna->id) { + case ETHTOOL_TX_COPYBREAK: + /* all the tx rings have the same tx_copybreak */ + *(u32 *)data = priv->tx_copybreak; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int hns3_set_tunable(struct net_device *netdev, + const struct ethtool_tunable *tuna, + const void *data) +{ + struct hns3_nic_priv *priv = netdev_priv(netdev); + struct hnae3_handle *h = priv->ae_handle; + int i, ret = 0; + + switch (tuna->id) { + case ETHTOOL_TX_COPYBREAK: + priv->tx_copybreak = *(u32 *)data; + + for (i = 0; i < h->kinfo.num_tqps; i++) + priv->ring[i].tx_copybreak = priv->tx_copybreak; + + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + #define HNS3_ETHTOOL_COALESCE (ETHTOOL_COALESCE_USECS | \ ETHTOOL_COALESCE_USE_ADAPTIVE | \ ETHTOOL_COALESCE_RX_USECS_HIGH | \ @@ -1635,6 +1682,8 @@ static const struct ethtool_ops hns3vf_ethtool_ops = { .set_msglevel = hns3_set_msglevel, .get_priv_flags = hns3_get_priv_flags, .set_priv_flags = hns3_set_priv_flags, + .get_tunable = hns3_get_tunable, + .set_tunable = hns3_set_tunable, };
static const struct ethtool_ops hns3_ethtool_ops = { @@ -1674,6 +1723,8 @@ static const struct ethtool_ops hns3_ethtool_ops = { .get_priv_flags = hns3_get_priv_flags, .set_priv_flags = hns3_set_priv_flags, .get_ts_info = hns3_get_ts_info, + .get_tunable = hns3_get_tunable, + .set_tunable = hns3_set_tunable, };
void hns3_ethtool_set_ops(struct net_device *netdev)
From: Huazhong Tan tanhuazhong@huawei.com
mainline inclusion from mainline-master commit 1a00197b7d2fe57f0be93037d5090e19a9b178c8 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Add support to query tx spare buffer size from configuration file, and use this info to do spare buffer initialization when the module parameter 'tx_spare_buf_size' is not specified.
Signed-off-by: Huazhong Tan tanhuazhong@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 7 +++++-- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 ++ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 14 ++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 ++ 5 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 13e2952c5da0..12db223dd71e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -759,6 +759,7 @@ struct hnae3_knic_private_info { u16 rx_buf_len; u16 num_tx_desc; u16 num_rx_desc; + u32 tx_spare_buf_size;
struct hnae3_tc_info tc_info;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index e5466daac1c4..d86b3735aa9f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1005,13 +1005,16 @@ static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) { struct hns3_tx_spare *tx_spare; struct page *page; + u32 alloc_size; dma_addr_t dma; int order;
- if (!tx_spare_buf_size) + alloc_size = tx_spare_buf_size ? tx_spare_buf_size : + ring->tqp->handle->kinfo.tx_spare_buf_size; + if (!alloc_size) return;
- order = get_order(tx_spare_buf_size); + order = get_order(alloc_size); tx_spare = devm_kzalloc(ring_to_dev(ring), sizeof(*tx_spare), GFP_KERNEL); if (!tx_spare) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 51be76f1795e..a322dfeba5cf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -542,6 +542,8 @@ struct hclge_pf_res_cmd { #define HCLGE_CFG_UMV_TBL_SPACE_M GENMASK(31, 16) #define HCLGE_CFG_PF_RSS_SIZE_S 0 #define HCLGE_CFG_PF_RSS_SIZE_M GENMASK(3, 0) +#define HCLGE_CFG_TX_SPARE_BUF_SIZE_S 4 +#define HCLGE_CFG_TX_SPARE_BUF_SIZE_M GENMASK(15, 4)
#define HCLGE_CFG_CMD_CNT 4
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index f6fdf93c8cad..f3e482ab3c71 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1279,6 +1279,7 @@ static u32 hclge_get_max_speed(u16 speed_ability)
static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc) { +#define HCLGE_TX_SPARE_SIZE_UNIT 4096 #define SPEED_ABILITY_EXT_SHIFT 8
struct hclge_cfg_param_cmd *req; @@ -1358,6 +1359,15 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc) cfg->pf_rss_size_max = cfg->pf_rss_size_max ? 1U << cfg->pf_rss_size_max : cfg->vf_rss_size_max; + + /* The unit of the tx spare buffer size queried from configuration + * file is HCLGE_TX_SPARE_SIZE_UNIT(4096) bytes, so a conversion is + * needed here. + */ + cfg->tx_spare_buf_size = hnae3_get_field(__le32_to_cpu(req->param[2]), + HCLGE_CFG_TX_SPARE_BUF_SIZE_M, + HCLGE_CFG_TX_SPARE_BUF_SIZE_S); + cfg->tx_spare_buf_size *= HCLGE_TX_SPARE_SIZE_UNIT; }
/* hclge_get_cfg: query the static parameter from flash @@ -1539,6 +1549,7 @@ static int hclge_configure(struct hclge_dev *hdev) hdev->tc_max = cfg.tc_num; hdev->tm_info.hw_pfc_map = 0; hdev->wanted_umv_size = cfg.umv_space; + hdev->tx_spare_buf_size = cfg.tx_spare_buf_size; if (cfg.vlan_fliter_cap == HCLGE_VLAN_FLTR_CAN_MDF) set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps);
@@ -1736,6 +1747,7 @@ static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps, kinfo->num_rx_desc = num_rx_desc;
kinfo->rx_buf_len = hdev->rx_buf_len; + kinfo->tx_spare_buf_size = hdev->tx_spare_buf_size;
kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, num_tqps, sizeof(struct hnae3_queue *), GFP_KERNEL); @@ -11059,6 +11071,8 @@ static void hclge_info_show(struct hclge_dev *hdev) hdev->flag & HCLGE_FLAG_DCB_ENABLE ? "enable" : "disable"); dev_info(dev, "MQPRIO %s\n", hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE ? "enable" : "disable"); + dev_info(dev, "Default tx spare buffer size: %u\n", + hdev->tx_spare_buf_size);
dev_info(dev, "PF info end.\n"); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 02852738ce21..3d3352491dba 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -384,6 +384,7 @@ struct hclge_cfg { u8 mac_addr[ETH_ALEN]; u8 default_speed; u32 numa_node_map; + u32 tx_spare_buf_size; u16 speed_ability; u16 umv_space; }; @@ -848,6 +849,7 @@ struct hclge_dev { u16 alloc_rss_size; /* Allocated RSS task queue */ u16 vf_rss_size_max; /* HW defined VF max RSS task queue */ u16 pf_rss_size_max; /* HW defined PF max RSS task queue */ + u32 tx_spare_buf_size; /* HW defined TX spare buffer size */
u16 fdir_pf_filter_count; /* Num of guaranteed filters for this PF */ u16 num_alloc_vport; /* Num vports this driver supports */
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit 7459775e9f658a2d5f3ff9d4d087e86f4d4e5b83 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Using the queue based tx buffer, it is also possible to allocate a sgl buffer, and use skb_to_sgvec() to convert the skb to the sgvec in order to support the dma_map_sg() to decreases the overhead of IOMMU mapping and unmapping.
Firstly, it reduces the number of buffers. For example, a tcp skb may have a 66-byte header and 3 fragments of 4328, 32768, and 28064 bytes. With this patch, dma_map_sg() will combine them into two buffers, 66-bytes header and one 65160-bytes fragment by using IOMMU.
Secondly, it reduces the number of dma mapping and unmapping. All the original 4 buffers are mapped only once rather than 4 times.
The throughput improves above 10% when running single thread of iperf using TCP when IOMMU is in strict mode.
Suggested-by: Barry Song song.bao.hua@hisilicon.com Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 111 +++++++++++++++++- .../net/ethernet/hisilicon/hns3/hns3_enet.h | 4 + .../ethernet/hisilicon/hns3/hns3_ethtool.c | 3 + 3 files changed, 113 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index d86b3735aa9f..f60a344a6a9f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -57,6 +57,15 @@ static unsigned int tx_spare_buf_size; module_param(tx_spare_buf_size, uint, 0400); MODULE_PARM_DESC(tx_spare_buf_size, "Size used to allocate tx spare buffer");
+static unsigned int tx_sgl = 1; +module_param(tx_sgl, uint, 0600); +MODULE_PARM_DESC(tx_sgl, "Minimum number of frags when using dma_map_sg() to optimize the IOMMU mapping"); + +#define HNS3_SGL_SIZE(nfrag) (sizeof(struct scatterlist) * (nfrag) + \ + sizeof(struct sg_table)) +#define HNS3_MAX_SGL_SIZE ALIGN(HNS3_SGL_SIZE(HNS3_MAX_TSO_BD_NUM),\ + dma_get_cache_alignment()) + #define DEFAULT_MSG_LEVEL (NETIF_MSG_PROBE | NETIF_MSG_LINK | \ NETIF_MSG_IFDOWN | NETIF_MSG_IFUP)
@@ -1001,6 +1010,25 @@ static bool hns3_can_use_tx_bounce(struct hns3_enet_ring *ring, return true; }
+static bool hns3_can_use_tx_sgl(struct hns3_enet_ring *ring, + struct sk_buff *skb, + u32 space) +{ + if (skb->len <= ring->tx_copybreak || !tx_sgl || + (!skb_has_frag_list(skb) && + skb_shinfo(skb)->nr_frags < tx_sgl)) + return false; + + if (space < HNS3_MAX_SGL_SIZE) { + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_spare_full++; + u64_stats_update_end(&ring->syncp); + return false; + } + + return true; +} + static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) { struct hns3_tx_spare *tx_spare; @@ -1108,14 +1136,19 @@ static void hns3_tx_spare_reclaim_cb(struct hns3_enet_ring *ring,
/* This tx spare buffer is only really reclaimed after calling * hns3_tx_spare_update(), so it is still safe to use the info in - * the tx buffer to do the dma sync after tx_spare->next_to_clean - * is moved forword. + * the tx buffer to do the dma sync or sg unmapping after + * tx_spare->next_to_clean is moved forword. */ if (cb->type & (DESC_TYPE_BOUNCE_HEAD | DESC_TYPE_BOUNCE_ALL)) { dma_addr_t dma = tx_spare->dma + ntc;
dma_sync_single_for_cpu(ring_to_dev(ring), dma, len, DMA_TO_DEVICE); + } else { + struct sg_table *sgt = tx_spare->buf + ntc; + + dma_unmap_sg(ring_to_dev(ring), sgt->sgl, sgt->orig_nents, + DMA_TO_DEVICE); } }
@@ -2058,6 +2091,65 @@ static int hns3_handle_tx_bounce(struct hns3_enet_ring *ring, return bd_num; }
+static int hns3_handle_tx_sgl(struct hns3_enet_ring *ring, + struct sk_buff *skb) +{ + struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; + u32 nfrag = skb_shinfo(skb)->nr_frags + 1; + struct sg_table *sgt; + int i, bd_num = 0; + dma_addr_t dma; + u32 cb_len; + int nents; + + if (skb_has_frag_list(skb)) + nfrag = HNS3_MAX_TSO_BD_NUM; + + /* hns3_can_use_tx_sgl() is called to ensure the below + * function can always return the tx buffer. + */ + sgt = hns3_tx_spare_alloc(ring, HNS3_SGL_SIZE(nfrag), + &dma, &cb_len); + + /* scatterlist follows by the sg table */ + sgt->sgl = (struct scatterlist *)(sgt + 1); + sg_init_table(sgt->sgl, nfrag); + nents = skb_to_sgvec(skb, sgt->sgl, 0, skb->len); + if (unlikely(nents < 0)) { + hns3_tx_spare_rollback(ring, cb_len); + u64_stats_update_begin(&ring->syncp); + ring->stats.skb2sgl_err++; + u64_stats_update_end(&ring->syncp); + return -ENOMEM; + } + + sgt->orig_nents = nents; + sgt->nents = dma_map_sg(ring_to_dev(ring), sgt->sgl, sgt->orig_nents, + DMA_TO_DEVICE); + if (unlikely(!sgt->nents)) { + hns3_tx_spare_rollback(ring, cb_len); + u64_stats_update_begin(&ring->syncp); + ring->stats.map_sg_err++; + u64_stats_update_end(&ring->syncp); + return -ENOMEM; + } + + desc_cb->priv = skb; + desc_cb->length = cb_len; + desc_cb->dma = dma; + desc_cb->type = DESC_TYPE_SGL_SKB; + + for (i = 0; i < sgt->nents; i++) + bd_num += hns3_fill_desc(ring, sg_dma_address(sgt->sgl + i), + sg_dma_len(sgt->sgl + i)); + + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_sgl++; + u64_stats_update_end(&ring->syncp); + + return bd_num; +} + static int hns3_handle_desc_filling(struct hns3_enet_ring *ring, struct sk_buff *skb) { @@ -2068,6 +2160,9 @@ static int hns3_handle_desc_filling(struct hns3_enet_ring *ring,
space = hns3_tx_spare_space(ring);
+ if (hns3_can_use_tx_sgl(ring, skb, space)) + return hns3_handle_tx_sgl(ring, skb); + if (hns3_can_use_tx_bounce(ring, skb, space)) return hns3_handle_tx_bounce(ring, skb);
@@ -2324,6 +2419,8 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_drop += ring->stats.over_max_recursion; tx_drop += ring->stats.hw_limitation; tx_drop += ring->stats.copy_bits_err; + tx_drop += ring->stats.skb2sgl_err; + tx_drop += ring->stats.map_sg_err; tx_errors += ring->stats.sw_err_cnt; tx_errors += ring->stats.tx_vlan_err; tx_errors += ring->stats.tx_l4_proto_err; @@ -2332,6 +2429,8 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_errors += ring->stats.over_max_recursion; tx_errors += ring->stats.hw_limitation; tx_errors += ring->stats.copy_bits_err; + tx_errors += ring->stats.skb2sgl_err; + tx_errors += ring->stats.map_sg_err; } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
/* fetch the rx stats */ @@ -3126,7 +3225,7 @@ static void hns3_free_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb, int budget) { if (cb->type & (DESC_TYPE_SKB | DESC_TYPE_BOUNCE_HEAD | - DESC_TYPE_BOUNCE_ALL)) + DESC_TYPE_BOUNCE_ALL | DESC_TYPE_SGL_SKB)) napi_consume_skb(cb->priv, budget); else if (!HNAE3_IS_TX_RING(ring) && cb->pagecnt_bias) __page_frag_cache_drain(cb->priv, cb->pagecnt_bias); @@ -3153,7 +3252,8 @@ static void hns3_unmap_buffer(struct hns3_enet_ring *ring, else if ((cb->type & DESC_TYPE_PAGE) && cb->length) dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length, ring_to_dma_dir(ring)); - else if (cb->type & (DESC_TYPE_BOUNCE_ALL | DESC_TYPE_BOUNCE_HEAD)) + else if (cb->type & (DESC_TYPE_BOUNCE_ALL | DESC_TYPE_BOUNCE_HEAD | + DESC_TYPE_SGL_SKB)) hns3_tx_spare_reclaim_cb(ring, cb); }
@@ -3307,7 +3407,8 @@ static bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring, desc_cb = &ring->desc_cb[ntc];
if (desc_cb->type & (DESC_TYPE_SKB | DESC_TYPE_BOUNCE_ALL | - DESC_TYPE_BOUNCE_HEAD)) { + DESC_TYPE_BOUNCE_HEAD | + DESC_TYPE_SGL_SKB)) { (*pkts)++; (*bytes) += desc_cb->send_bytes; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 8d147c1dab2c..22ae291471aa 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -306,6 +306,7 @@ enum hns3_desc_type { DESC_TYPE_PAGE = 1 << 2, DESC_TYPE_BOUNCE_ALL = 1 << 3, DESC_TYPE_BOUNCE_HEAD = 1 << 4, + DESC_TYPE_SGL_SKB = 1 << 5, };
struct hns3_desc_cb { @@ -410,6 +411,9 @@ struct ring_stats { u64 tx_bounce; u64 tx_spare_full; u64 copy_bits_err; + u64 tx_sgl; + u64 skb2sgl_err; + u64 map_sg_err; }; struct { u64 rx_pkts; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index f306de16d73f..d7852716aaad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -49,6 +49,9 @@ static const struct hns3_stats hns3_txq_stats[] = { HNS3_TQP_STAT("bounce", tx_bounce), HNS3_TQP_STAT("spare_full", tx_spare_full), HNS3_TQP_STAT("copy_bits_err", copy_bits_err), + HNS3_TQP_STAT("sgl", tx_sgl), + HNS3_TQP_STAT("skb2sgl_err", skb2sgl_err), + HNS3_TQP_STAT("map_sg_err", map_sg_err), };
#define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats)
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit fa7711b888f24ee9291d90f8fbdaccfc80ed72c7 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Current rx page offset only reset to zero when all the below conditions are satisfied: 1. rx page is only owned by driver. 2. rx page is reusable. 3. the page offset that is above to be given to the stack has reached the end of the page.
If the page offset is over the hns3_buf_size(), it means the buffer below the offset of the page is usable when the above condition 1 & 2 are satisfied, so page offset can be reset to zero instead of increasing the offset. We may be able to always reuse the first 4K buffer of a 64K page, which means we can limit the hot buffer size as much as possible.
The above optimization is a side effect when refacting the rx page reuse handling in order to support the rx copybreak.
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index f60a344a6a9f..98e8a548edb8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3525,7 +3525,7 @@ static void hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring,
static bool hns3_can_reuse_page(struct hns3_desc_cb *cb) { - return (page_count(cb->priv) - cb->pagecnt_bias) == 1; + return page_count(cb->priv) == cb->pagecnt_bias; }
static void hns3_nic_reuse_page(struct sk_buff *skb, int i, @@ -3533,40 +3533,40 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, struct hns3_desc_cb *desc_cb) { struct hns3_desc *desc = &ring->desc[ring->next_to_clean]; + u32 frag_offset = desc_cb->page_offset + pull_len; int size = le16_to_cpu(desc->rx.size); u32 truesize = hns3_buf_size(ring); + u32 frag_size = size - pull_len;
- desc_cb->pagecnt_bias--; - skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, - size - pull_len, truesize); + /* Avoid re-using remote or pfmem page */ + if (unlikely(!dev_page_is_reusable(desc_cb->priv))) + goto out;
- /* Avoid re-using remote and pfmemalloc pages, or the stack is still - * using the page when page_offset rollback to zero, flag default - * unreuse + /* Stack is not using and current page_offset is non-zero, we can + * reuse from the zero offset. */ - if (!dev_page_is_reusable(desc_cb->priv) || - (!desc_cb->page_offset && !hns3_can_reuse_page(desc_cb))) { - __page_frag_cache_drain(desc_cb->priv, desc_cb->pagecnt_bias); - return; - } - - /* Move offset up to the next cache line */ - desc_cb->page_offset += truesize; - - if (desc_cb->page_offset + truesize <= hns3_page_size(ring)) { + if (desc_cb->page_offset && hns3_can_reuse_page(desc_cb)) { + desc_cb->page_offset = 0; desc_cb->reuse_flag = 1; - } else if (hns3_can_reuse_page(desc_cb)) { + } else if (desc_cb->page_offset + truesize * 2 <= + hns3_page_size(ring)) { + desc_cb->page_offset += truesize; desc_cb->reuse_flag = 1; - desc_cb->page_offset = 0; - } else if (desc_cb->pagecnt_bias) { - __page_frag_cache_drain(desc_cb->priv, desc_cb->pagecnt_bias); - return; }
+out: + desc_cb->pagecnt_bias--; + if (unlikely(!desc_cb->pagecnt_bias)) { page_ref_add(desc_cb->priv, USHRT_MAX); desc_cb->pagecnt_bias = USHRT_MAX; } + + skb_add_rx_frag(skb, i, desc_cb->priv, frag_offset, + frag_size, truesize); + + if (unlikely(!desc_cb->reuse_flag)) + __page_frag_cache_drain(desc_cb->priv, desc_cb->pagecnt_bias); }
static int hns3_gro_complete(struct sk_buff *skb, u32 l234info)
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit 99f6b5fb5f63cf69c6e56bba8e5492c98c521a63 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Currently rx page will be reused to receive future packet when the stack releases the previous skb quickly. If the old page can not be reused, a new page will be allocated and mapped, which comsumes a lot of cpu when IOMMU is in the strict mode, especially when the application and irq/NAPI happens to run on the same cpu.
So allocate a new frag to memcpy the data to avoid the costly IOMMU unmapping/mapping operation, and add "frag_alloc_err" and "frag_alloc" stats in "ethtool -S ethX" cmd.
The throughput improves above 50% when running single thread of iperf using TCP when IOMMU is in strict mode and iperf shares the same cpu with irq/NAPI(rx_copybreak = 2048 and mtu = 1500).
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 2 ++ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 23 +++++++++++++++++++ .../net/ethernet/hisilicon/hns3/hns3_enet.h | 4 ++++ .../ethernet/hisilicon/hns3/hns3_ethtool.c | 12 ++++++++++ 4 files changed, 41 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index a24a75c47cad..34b6cd904a1a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -450,6 +450,7 @@ static const struct hns3_dbg_item rx_queue_info_items[] = { { "HEAD", 2 }, { "FBDNUM", 2 }, { "PKTNUM", 2 }, + { "COPYBREAK", 2 }, { "RING_EN", 2 }, { "RX_RING_EN", 2 }, { "BASE_ADDR", 10 }, @@ -481,6 +482,7 @@ static void hns3_dump_rx_queue_info(struct hns3_enet_ring *ring,
sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_PKTNUM_RECORD_REG)); + sprintf(result[j++], "%9u", ring->rx_copybreak);
sprintf(result[j++], "%7s", readl_relaxed(ring->tqp->io_base + HNS3_RING_EN_REG) ? "on" : "off"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 98e8a548edb8..51bbf5f760c5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3552,6 +3552,28 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, hns3_page_size(ring)) { desc_cb->page_offset += truesize; desc_cb->reuse_flag = 1; + } else if (frag_size <= ring->rx_copybreak) { + void *frag = napi_alloc_frag(frag_size); + + if (unlikely(!frag)) { + u64_stats_update_begin(&ring->syncp); + ring->stats.frag_alloc_err++; + u64_stats_update_end(&ring->syncp); + + hns3_rl_err(ring_to_netdev(ring), + "failed to allocate rx frag\n"); + goto out; + } + + desc_cb->reuse_flag = 1; + memcpy(frag, desc_cb->buf + frag_offset, frag_size); + skb_add_rx_frag(skb, i, virt_to_page(frag), + offset_in_page(frag), frag_size, frag_size); + + u64_stats_update_begin(&ring->syncp); + ring->stats.frag_alloc++; + u64_stats_update_end(&ring->syncp); + return; }
out: @@ -4620,6 +4642,7 @@ static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, ring = &priv->ring[q->tqp_index + queue_num]; desc_num = priv->ae_handle->kinfo.num_rx_desc; ring->queue_index = q->tqp_index; + ring->rx_copybreak = priv->rx_copybreak; }
hnae3_set_bit(ring->flag, HNAE3_RING_TYPE_B, ring_type); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 22ae291471aa..15af3d93857b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -427,6 +427,8 @@ struct ring_stats { u64 csum_complete; u64 rx_multicast; u64 non_reuse_pg; + u64 frag_alloc_err; + u64 frag_alloc; }; __le16 csum; }; @@ -478,6 +480,7 @@ struct hns3_enet_ring { /* for Rx ring */ struct { u32 pull_len; /* memcpy len for current rx packet */ + u32 rx_copybreak; u32 frag_num; /* first buffer address for current packet */ unsigned char *va; @@ -569,6 +572,7 @@ struct hns3_nic_priv { struct hns3_enet_coalesce tx_coal; struct hns3_enet_coalesce rx_coal; u32 tx_copybreak; + u32 rx_copybreak; };
union l3_hdr_info { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index d7852716aaad..82061ab6930f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -71,6 +71,8 @@ static const struct hns3_stats hns3_rxq_stats[] = { HNS3_TQP_STAT("csum_complete", csum_complete), HNS3_TQP_STAT("multicast", rx_multicast), HNS3_TQP_STAT("non_reuse_pg", non_reuse_pg), + HNS3_TQP_STAT("frag_alloc_err", frag_alloc_err), + HNS3_TQP_STAT("frag_alloc", frag_alloc), };
#define HNS3_PRIV_FLAGS_LEN ARRAY_SIZE(hns3_priv_flags) @@ -1610,6 +1612,9 @@ static int hns3_get_tunable(struct net_device *netdev, /* all the tx rings have the same tx_copybreak */ *(u32 *)data = priv->tx_copybreak; break; + case ETHTOOL_RX_COPYBREAK: + *(u32 *)data = priv->rx_copybreak; + break; default: ret = -EOPNOTSUPP; break; @@ -1633,6 +1638,13 @@ static int hns3_set_tunable(struct net_device *netdev, for (i = 0; i < h->kinfo.num_tqps; i++) priv->ring[i].tx_copybreak = priv->tx_copybreak;
+ break; + case ETHTOOL_RX_COPYBREAK: + priv->rx_copybreak = *(u32 *)data; + + for (i = h->kinfo.num_tqps; i < h->kinfo.num_tqps * 2; i++) + priv->ring[i].rx_copybreak = priv->rx_copybreak; + break; default: ret = -EOPNOTSUPP;
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-master commit 961045004b774aae7a244fa0435f8a6a2495c234 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
In the current rx page reuse handling process, the rx page buffer may have conflict between driver and stack in high-pressure scenario.
To fix this problem, we need to check whether the page is only owned by driver at the begin and at the end of a page to make sure there is no reuse conflict between driver and stack when desc_cb->page_offset is rollbacked to zero or increased.
Fixes: fa7711b888f2 ("net: hns3: optimize the rx page reuse handling process") Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 51bbf5f760c5..cdb5f14fb6bc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3537,21 +3537,33 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, int size = le16_to_cpu(desc->rx.size); u32 truesize = hns3_buf_size(ring); u32 frag_size = size - pull_len; + bool reused;
/* Avoid re-using remote or pfmem page */ if (unlikely(!dev_page_is_reusable(desc_cb->priv))) goto out;
- /* Stack is not using and current page_offset is non-zero, we can - * reuse from the zero offset. + reused = hns3_can_reuse_page(desc_cb); + + /* Rx page can be reused when: + * 1. Rx page is only owned by the driver when page_offset + * is zero, which means 0 @ truesize will be used by + * stack after skb_add_rx_frag() is called, and the rest + * of rx page can be reused by driver. + * Or + * 2. Rx page is only owned by the driver when page_offset + * is non-zero, which means page_offset @ truesize will + * be used by stack after skb_add_rx_frag() is called, + * and 0 @ truesize can be reused by driver. */ - if (desc_cb->page_offset && hns3_can_reuse_page(desc_cb)) { - desc_cb->page_offset = 0; - desc_cb->reuse_flag = 1; - } else if (desc_cb->page_offset + truesize * 2 <= - hns3_page_size(ring)) { + if ((!desc_cb->page_offset && reused) || + ((desc_cb->page_offset + truesize + truesize) <= + hns3_page_size(ring) && desc_cb->page_offset)) { desc_cb->page_offset += truesize; desc_cb->reuse_flag = 1; + } else if (desc_cb->page_offset && reused) { + desc_cb->page_offset = 0; + desc_cb->reuse_flag = 1; } else if (frag_size <= ring->rx_copybreak) { void *frag = napi_alloc_frag(frag_size);
From: Dan Carpenter dan.carpenter@oracle.com
mainline inclusion from mainline-master commit faebad853455b7126450c1690f7c31e048213543 category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
This patch doesn't affect runtime at all, it's just a correctness issue.
The ptp->info.name[] buffer has 16 characters but the snprintf() limit was capped at 32 characters. Fortunately, HCLGE_DRIVER_NAME is "hclge" which isn't close to 16 characters so we're fine.
Fixes: 0bf5eb788512 ("net: hns3: add support for PTP") Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c index b3eb8f109dbb..3b1f84502e36 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c @@ -415,8 +415,6 @@ int hclge_ptp_get_ts_info(struct hnae3_handle *handle,
static int hclge_ptp_create_clock(struct hclge_dev *hdev) { -#define HCLGE_PTP_NAME_LEN 32 - struct hclge_ptp *ptp;
ptp = devm_kzalloc(&hdev->pdev->dev, sizeof(*ptp), GFP_KERNEL); @@ -424,7 +422,7 @@ static int hclge_ptp_create_clock(struct hclge_dev *hdev) return -ENOMEM;
ptp->hdev = hdev; - snprintf(ptp->info.name, HCLGE_PTP_NAME_LEN, "%s", + snprintf(ptp->info.name, sizeof(ptp->info.name), "%s", HCLGE_DRIVER_NAME); ptp->info.owner = THIS_MODULE; ptp->info.max_adj = HCLGE_PTP_CYCLE_ADJ_MAX;
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
mainline inclusion from mainline-master commit b40d7af798a0a459d65bd95f34e3dff004eb554a category: bugfix bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
If this 'kzalloc()' fails we must free some resources as in all the other error handling paths of this function.
Fixes: 2e2deee7618b ("net: hns3: add the RAS compatibility adaptation solution") Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Reviewed-by: Jiaran Zhang zhangjiaran@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index bad9fda19398..ec9a7f8bc3fe 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -2330,8 +2330,10 @@ int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev) buf_size = buf_len / sizeof(u32);
desc_data = kzalloc(buf_len, GFP_KERNEL); - if (!desc_data) - return -ENOMEM; + if (!desc_data) { + ret = -ENOMEM; + goto err_desc; + }
buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) {
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit 03a92fe8cedb6f619df416d38d0b57fd55070cd7 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
Previously, the flow director counter is not enabled. To improve the maintainability for chechking whether flow director hit or not, enable flow director counter for each function, and add debugfs query inerface to query the counters for each function.
The debugfs command is below: cat fd_counter func_id hit_times pf 0 vf0 0 vf1 0
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 7 ++++ .../hisilicon/hns3/hns3pf/hclge_cmd.h | 9 +++++ .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 37 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 10 ++++- 5 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 12db223dd71e..b23e71752045 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -289,6 +289,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_RX_QUEUE_INFO, HNAE3_DBG_CMD_TX_QUEUE_INFO, HNAE3_DBG_CMD_FD_TCAM, + HNAE3_DBG_CMD_FD_COUNTER, HNAE3_DBG_CMD_MAC_TNL_STATUS, HNAE3_DBG_CMD_SERV_INFO, HNAE3_DBG_CMD_UNKNOWN, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 34b6cd904a1a..b72fdb94df63 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -323,6 +323,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "fd_counter", + .cmd = HNAE3_DBG_CMD_FD_COUNTER, + .dentry = HNS3_DBG_DENTRY_FD, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index a322dfeba5cf..18bde77ef944 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -248,6 +248,7 @@ enum hclge_opcode_type { HCLGE_OPC_FD_KEY_CONFIG = 0x1202, HCLGE_OPC_FD_TCAM_OP = 0x1203, HCLGE_OPC_FD_AD_OP = 0x1204, + HCLGE_OPC_FD_CNT_OP = 0x1205, HCLGE_OPC_FD_USER_DEF_OP = 0x1207,
/* MDIO command */ @@ -1109,6 +1110,14 @@ struct hclge_fd_ad_config_cmd { u8 rsv2[8]; };
+struct hclge_fd_ad_cnt_read_cmd { + u8 rsv0[4]; + __le16 index; + u8 rsv1[2]; + __le64 cnt; + u8 rsv2[8]; +}; + #define HCLGE_FD_USER_DEF_OFT_S 0 #define HCLGE_FD_USER_DEF_OFT_M GENMASK(14, 0) #define HCLGE_FD_USER_DEF_EN_B 15 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 6fc50d09b9db..b69c54d365a7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1549,6 +1549,39 @@ static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len) return ret; }
+static int hclge_dbg_dump_fd_counter(struct hclge_dev *hdev, char *buf, int len) +{ + u8 func_num = pci_num_vf(hdev->pdev) + 1; /* pf and enabled vf num */ + struct hclge_fd_ad_cnt_read_cmd *req; + char str_id[HCLGE_DBG_ID_LEN]; + struct hclge_desc desc; + int pos = 0; + int ret; + u64 cnt; + u8 i; + + pos += scnprintf(buf + pos, len - pos, + "func_id\thit_times\n"); + + for (i = 0; i < func_num; i++) { + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_FD_CNT_OP, true); + req = (struct hclge_fd_ad_cnt_read_cmd *)desc.data; + req->index = cpu_to_le16(i); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, "failed to get fd counter, ret = %d\n", + ret); + return ret; + } + cnt = le64_to_cpu(req->cnt); + hclge_dbg_get_func_id_str(str_id, i); + pos += scnprintf(buf + pos, len - pos, + "%s\t%llu\n", str_id, cnt); + } + + return 0; +} + int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len) { int pos = 0; @@ -2375,6 +2408,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_VLAN_CONFIG, .dbg_dump = hclge_dbg_dump_vlan_config, }, + { + .cmd = HNAE3_DBG_CMD_FD_COUNTER, + .dbg_dump = hclge_dbg_dump_fd_counter, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index f3e482ab3c71..dd3354a57c62 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6000,8 +6000,14 @@ static int hclge_config_action(struct hclge_dev *hdev, u8 stage, ad_data.queue_id = rule->queue_id; }
- ad_data.use_counter = false; - ad_data.counter_id = 0; + if (hdev->fd_cfg.cnt_num[HCLGE_FD_STAGE_1]) { + ad_data.use_counter = true; + ad_data.counter_id = rule->vf_id % + hdev->fd_cfg.cnt_num[HCLGE_FD_STAGE_1]; + } else { + ad_data.use_counter = false; + ad_data.counter_id = 0; + }
ad_data.use_next_stage = false; ad_data.next_input_key = 0;
From: Jian Shen shenjian15@huawei.com
mainline inclusion from mainline-master commit d59daf6a4ceedf342f349e94f1300e1598213252 category: feature bugzilla: 173966 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------------------------------------
This patch adds support of dumping MAC umv counter in debugfs, which will be helpful for debugging.
The display style is below: $ cat umv_info num_alloc_vport : 2 max_umv_size : 256 wanted_umv_size : 256 priv_umv_size : 85 share_umv_size : 86 vport(0) used_umv_num : 1 vport(1) used_umv_num : 1
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Reviewed-by: Yongxin Li liyongxin1@huawei.com Signed-off-by: Junxin Chen chenjunxin1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3_debugfs.c | 7 ++++ .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index b23e71752045..f44a63b387dc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -292,6 +292,7 @@ enum hnae3_dbg_cmd { HNAE3_DBG_CMD_FD_COUNTER, HNAE3_DBG_CMD_MAC_TNL_STATUS, HNAE3_DBG_CMD_SERV_INFO, + HNAE3_DBG_CMD_UMV_INFO, HNAE3_DBG_CMD_UNKNOWN, };
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index b72fdb94df63..532523069d74 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -330,6 +330,13 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .buf_len = HNS3_DBG_READ_LEN, .init = hns3_dbg_common_file_init, }, + { + .name = "umv_info", + .cmd = HNAE3_DBG_CMD_UMV_INFO, + .dentry = HNS3_DBG_DENTRY_COMMON, + .buf_len = HNS3_DBG_READ_LEN, + .init = hns3_dbg_common_file_init, + }, };
static struct hns3_dbg_cap_info hns3_dbg_cap[] = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index b69c54d365a7..288788186ecc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -1927,6 +1927,36 @@ static void hclge_dbg_dump_mac_list(struct hclge_dev *hdev, char *buf, int len, } }
+static int hclge_dbg_dump_umv_info(struct hclge_dev *hdev, char *buf, int len) +{ + u8 func_num = pci_num_vf(hdev->pdev) + 1; + struct hclge_vport *vport; + int pos = 0; + u8 i; + + pos += scnprintf(buf, len, "num_alloc_vport : %u\n", + hdev->num_alloc_vport); + pos += scnprintf(buf + pos, len - pos, "max_umv_size : %u\n", + hdev->max_umv_size); + pos += scnprintf(buf + pos, len - pos, "wanted_umv_size : %u\n", + hdev->wanted_umv_size); + pos += scnprintf(buf + pos, len - pos, "priv_umv_size : %u\n", + hdev->priv_umv_size); + + mutex_lock(&hdev->vport_lock); + pos += scnprintf(buf + pos, len - pos, "share_umv_size : %u\n", + hdev->share_umv_size); + for (i = 0; i < func_num; i++) { + vport = &hdev->vport[i]; + pos += scnprintf(buf + pos, len - pos, + "vport(%u) used_umv_num : %u\n", + i, vport->used_umv_num); + } + mutex_unlock(&hdev->vport_lock); + + return 0; +} + static int hclge_get_vlan_rx_offload_cfg(struct hclge_dev *hdev, u8 vf_id, struct hclge_dbg_vlan_cfg *vlan_cfg) { @@ -2412,6 +2442,10 @@ static const struct hclge_dbg_func hclge_dbg_cmd_func[] = { .cmd = HNAE3_DBG_CMD_FD_COUNTER, .dbg_dump = hclge_dbg_dump_fd_counter, }, + { + .cmd = HNAE3_DBG_CMD_UMV_INFO, + .dbg_dump = hclge_dbg_dump_umv_info, + }, };
int hclge_dbg_read_cmd(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd,