AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/10/22 23:07 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The changes in this patch series are entirely confined to the Huawei HiNIC3 driver (drivers/net/ethernet/huawei/hinic3/), which is a vendor-specific Ethernet PCIe driver for Huawei SmartNIC hardware. This driver requires proprietary physical PCIe ASIC hardware (Huawei PCI vendor ID 0x19e5, device IDs 0x0222 and 0x375f) that is not emulated in standard virtualized environments (QEMU or GCE). Consequently, the modified code is structurally unreachable for fuzzing.",
  "WorthFuzzing": false
}

1/1 2026/10/22 23:07 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 490853b8fa97d00ec9df421558110d4e58e27a7f\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Oct 22 23:07:25 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c\nindex 90fc16288de95..3005441056f92 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c\n@@ -13,8 +13,11 @@\n \n #include \"hinic3_lld.h\"\n #include \"hinic3_hw_comm.h\"\n+#include \"hinic3_hwif.h\"\n #include \"hinic3_nic_dev.h\"\n #include \"hinic3_nic_cfg.h\"\n+#include \"hinic3_tx.h\"\n+#include \"hinic3_rx.h\"\n \n #define HINIC3_MGMT_VERSION_MAX_LEN     32\n \n@@ -409,6 +412,502 @@ hinic3_get_link_ksettings(struct net_device *netdev,\n \treturn 0;\n }\n \n+struct hinic3_stats {\n+\tchar name[ETH_GSTRING_LEN];\n+\tint  offset;\n+};\n+\n+#define HINIC3_STAT_SIZE_CHECK(type, member) \\\n+\tBUILD_BUG_ON_ZERO(sizeof_field(type, member) != sizeof(u64))\n+\n+#define HINIC3_FUNC_STAT(_stat_item) {\t\\\n+\t.name   = #_stat_item, \\\n+\t.offset = offsetof(struct l2nic_vport_stats, _stat_item) \\\n+\t\t  + 0 * HINIC3_STAT_SIZE_CHECK(struct l2nic_vport_stats, \\\n+\t\t\t\t\t       _stat_item) \\\n+}\n+\n+static struct hinic3_stats hinic3_function_stats[] = {\n+\tHINIC3_FUNC_STAT(tx_unicast_pkts_vport),\n+\tHINIC3_FUNC_STAT(tx_unicast_bytes_vport),\n+\tHINIC3_FUNC_STAT(tx_broadcast_pkts_vport),\n+\tHINIC3_FUNC_STAT(tx_broadcast_bytes_vport),\n+\n+\tHINIC3_FUNC_STAT(rx_unicast_pkts_vport),\n+\tHINIC3_FUNC_STAT(rx_unicast_bytes_vport),\n+\tHINIC3_FUNC_STAT(rx_broadcast_pkts_vport),\n+\tHINIC3_FUNC_STAT(rx_broadcast_bytes_vport),\n+};\n+\n+#define HINIC3_PORT_STAT(_stat_item) { \\\n+\t.name   = #_stat_item, \\\n+\t.offset = offsetof(struct mag_cmd_port_stats, _stat_item) \\\n+\t\t  + 0 * HINIC3_STAT_SIZE_CHECK(struct mag_cmd_port_stats, \\\n+\t\t\t\t\t       _stat_item) \\\n+}\n+\n+static struct hinic3_stats hinic3_port_stats[] = {\n+\tHINIC3_PORT_STAT(mac_tx_fragment_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_undersize_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_undermin_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_jumbo_bad_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_jumbo_good_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_oversize_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_jabber_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_bad_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_bad_octs),\n+\tHINIC3_PORT_STAT(mac_tx_total_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_uni_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_err_all_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_from_app_good_pkts),\n+\tHINIC3_PORT_STAT(mac_tx_from_app_bad_pkts),\n+\n+\tHINIC3_PORT_STAT(mac_rx_undermin_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_jumbo_bad_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_jumbo_good_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_bad_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_bad_octs),\n+\tHINIC3_PORT_STAT(mac_rx_total_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_uni_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_send_app_good_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_send_app_bad_pkts),\n+\tHINIC3_PORT_STAT(mac_rx_unfilter_pkts),\n+};\n+\n+#define HINIC3_TXQ_STAT(_stat_item) { \\\n+\t.name   = \"txq%d_\"#_stat_item, \\\n+\t.offset = offsetof(struct hinic3_txq_stats, _stat_item) \\\n+\t\t  + 0 * HINIC3_STAT_SIZE_CHECK(struct hinic3_txq_stats, \\\n+\t\t\t\t\t       _stat_item) \\\n+}\n+\n+#define HINIC3_RXQ_STAT(_stat_item) { \\\n+\t.name   = \"rxq%d_\"#_stat_item, \\\n+\t.offset = offsetof(struct hinic3_rxq_stats, _stat_item) \\\n+\t\t  + 0 * HINIC3_STAT_SIZE_CHECK(struct hinic3_rxq_stats, \\\n+\t\t\t\t\t       _stat_item) \\\n+}\n+\n+static struct hinic3_stats hinic3_tx_queue_stats[] = {\n+\tHINIC3_TXQ_STAT(skb_pad_err),\n+\tHINIC3_TXQ_STAT(offload_cow_skb_err),\n+\tHINIC3_TXQ_STAT(map_frag_err),\n+\tHINIC3_TXQ_STAT(unknown_tunnel_pkt),\n+};\n+\n+static struct hinic3_stats hinic3_rx_queue_stats[] = {\n+\tHINIC3_RXQ_STAT(other_errors),\n+\tHINIC3_RXQ_STAT(rx_buf_empty),\n+};\n+\n+static u16 hinic3_get_hw_stats_strings(struct hinic3_nic_dev *nic_dev, u8 *p)\n+{\n+\tu16 i, cnt = 0;\n+\n+\tfor (i = 0; i \u003c ARRAY_SIZE(hinic3_function_stats); i++) {\n+\t\tethtool_puts(\u0026p, hinic3_function_stats[i].name);\n+\t\tcnt++;\n+\t}\n+\n+\tif (!HINIC3_IS_VF(nic_dev-\u003ehwdev)) {\n+\t\tfor (i = 0; i \u003c ARRAY_SIZE(hinic3_port_stats); i++) {\n+\t\t\tethtool_puts(\u0026p, hinic3_port_stats[i].name);\n+\t\t\tcnt++;\n+\t\t}\n+\t}\n+\n+\treturn cnt;\n+}\n+\n+static void hinic3_get_qp_stats_strings(struct hinic3_nic_dev *nic_dev, u8 *p)\n+{\n+\tu16 i, j;\n+\n+\tfor (i = 0; i \u003c nic_dev-\u003eq_params.num_qps; i++) {\n+\t\tfor (j = 0; j \u003c ARRAY_SIZE(hinic3_tx_queue_stats); j++)\n+\t\t\tethtool_sprintf(\u0026p,\n+\t\t\t\t\thinic3_tx_queue_stats[j].name, i);\n+\t}\n+\n+\tfor (i = 0; i \u003c nic_dev-\u003eq_params.num_qps; i++) {\n+\t\tfor (j = 0; j \u003c ARRAY_SIZE(hinic3_rx_queue_stats); j++)\n+\t\t\tethtool_sprintf(\u0026p,\n+\t\t\t\t\thinic3_rx_queue_stats[j].name, i);\n+\t}\n+}\n+\n+static void hinic3_get_strings(struct net_device *netdev,\n+\t\t\t       u32 stringset, u8 *data)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tu16 offset;\n+\n+\tswitch (stringset) {\n+\tcase ETH_SS_STATS:\n+\t\toffset = hinic3_get_hw_stats_strings(nic_dev, data);\n+\t\thinic3_get_qp_stats_strings(nic_dev,\n+\t\t\t\t\t    data + offset * ETH_GSTRING_LEN);\n+\n+\t\tbreak;\n+\t}\n+}\n+\n+static int hinic3_get_sset_count(struct net_device *netdev, int sset)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tint count, q_num;\n+\n+\tswitch (sset) {\n+\tcase ETH_SS_STATS:\n+\t\tq_num = nic_dev-\u003eq_params.num_qps;\n+\t\tcount = ARRAY_SIZE(hinic3_function_stats) +\n+\t\t\t(ARRAY_SIZE(hinic3_tx_queue_stats) +\n+\t\t\t ARRAY_SIZE(hinic3_rx_queue_stats)) *\n+\t\t\tq_num;\n+\n+\t\tif (!HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\t\tcount += ARRAY_SIZE(hinic3_port_stats);\n+\n+\t\treturn count;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n+static u16 hinic3_get_ethtool_port_stats(struct net_device *netdev, u64 *data)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct mag_cmd_port_stats *ps;\n+\tu16 i = 0, j;\n+\tchar *p;\n+\tint err;\n+\n+\tps = kmalloc_obj(*ps);\n+\tif (!ps)\n+\t\tgoto err_zero_stats;\n+\n+\terr = hinic3_get_phy_port_stats(nic_dev-\u003ehwdev, ps);\n+\tif (err) {\n+\t\tkfree(ps);\n+\t\tnetdev_err_once(netdev, \"Failed to get port stats from fw\\n\");\n+\t\tgoto err_zero_stats;\n+\t}\n+\n+\tfor (j = 0; j \u003c ARRAY_SIZE(hinic3_port_stats); j++, i++) {\n+\t\tp = (char *)ps + hinic3_port_stats[j].offset;\n+\t\tdata[i] = le64_to_cpu(*(__le64 *)p);\n+\t}\n+\n+\tkfree(ps);\n+\n+\treturn i;\n+\n+err_zero_stats:\n+\tmemset(\u0026data[i], 0, ARRAY_SIZE(hinic3_port_stats) * sizeof(*data));\n+\n+\treturn i + ARRAY_SIZE(hinic3_port_stats);\n+}\n+\n+static void hinic3_get_drv_queue_stats(struct net_device *netdev, u64 *data)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct hinic3_txq_stats txq_stats = {};\n+\tstruct hinic3_rxq_stats rxq_stats = {};\n+\tu16 i = 0, j, qid;\n+\tchar *p;\n+\n+\tfor (qid = 0; qid \u003c nic_dev-\u003eq_params.num_qps; qid++) {\n+\t\thinic3_txq_get_stats(\u0026nic_dev-\u003etxqs[qid], \u0026txq_stats);\n+\t\tfor (j = 0; j \u003c ARRAY_SIZE(hinic3_tx_queue_stats); j++, i++) {\n+\t\t\tp = (char *)\u0026txq_stats +\n+\t\t\t    hinic3_tx_queue_stats[j].offset;\n+\t\t\tdata[i] = *(u64 *)p;\n+\t\t}\n+\t}\n+\n+\ti = nic_dev-\u003eq_params.num_qps * ARRAY_SIZE(hinic3_tx_queue_stats);\n+\tfor (qid = 0; qid \u003c nic_dev-\u003eq_params.num_qps; qid++) {\n+\t\thinic3_rxq_get_stats(\u0026nic_dev-\u003erxqs[qid], \u0026rxq_stats);\n+\t\tfor (j = 0; j \u003c ARRAY_SIZE(hinic3_rx_queue_stats); j++, i++) {\n+\t\t\tp = (char *)\u0026rxq_stats +\n+\t\t\t    hinic3_rx_queue_stats[j].offset;\n+\t\t\tdata[i] = *(u64 *)p;\n+\t\t}\n+\t}\n+}\n+\n+static void hinic3_get_ethtool_stats(struct net_device *netdev,\n+\t\t\t\t     struct ethtool_stats *stats, u64 *data)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct l2nic_vport_stats vport_stats = {};\n+\tu16 i = 0, j;\n+\tchar *p;\n+\tint err;\n+\n+\terr = hinic3_get_vport_stats(nic_dev-\u003ehwdev,\n+\t\t\t\t     hinic3_global_func_id(nic_dev-\u003ehwdev),\n+\t\t\t\t     \u0026vport_stats);\n+\tif (err)\n+\t\tnetdev_err_once(netdev,\n+\t\t\t\t\"Failed to get function stats from fw\\n\");\n+\n+\tfor (j = 0; j \u003c ARRAY_SIZE(hinic3_function_stats); j++, i++) {\n+\t\tp = (char *)\u0026vport_stats + hinic3_function_stats[j].offset;\n+\t\tdata[i] = le64_to_cpu(*(__le64 *)p);\n+\t}\n+\n+\tif (!HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\ti += hinic3_get_ethtool_port_stats(netdev, data + i);\n+\n+\thinic3_get_drv_queue_stats(netdev, data + i);\n+}\n+\n+static void hinic3_get_eth_phy_stats(struct net_device *netdev,\n+\t\t\t\t     struct ethtool_eth_phy_stats *phy_stats)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct mag_cmd_port_stats *ps;\n+\tint err;\n+\n+\tif (HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\treturn;\n+\n+\tps = kmalloc_obj(*ps);\n+\tif (!ps)\n+\t\treturn;\n+\n+\terr = hinic3_get_phy_port_stats(nic_dev-\u003ehwdev, ps);\n+\tif (err) {\n+\t\tkfree(ps);\n+\t\tnetdev_err_once(netdev,\n+\t\t\t\t\"Failed to get eth phy stats from fw\\n\");\n+\t\treturn;\n+\t}\n+\n+\tphy_stats-\u003eSymbolErrorDuringCarrier =\n+\t\tle64_to_cpu(ps-\u003emac_rx_sym_err_pkts);\n+\n+\tkfree(ps);\n+}\n+\n+static void hinic3_get_eth_mac_stats(struct net_device *netdev,\n+\t\t\t\t     struct ethtool_eth_mac_stats *mac_stats)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct mag_cmd_port_stats *ps;\n+\tint err;\n+\n+\tif (HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\treturn;\n+\n+\tps = kmalloc_obj(*ps);\n+\tif (!ps)\n+\t\treturn;\n+\n+\terr = hinic3_get_phy_port_stats(nic_dev-\u003ehwdev, ps);\n+\tif (err) {\n+\t\tkfree(ps);\n+\t\tnetdev_err_once(netdev,\n+\t\t\t\t\"Failed to get eth mac stats from fw\\n\");\n+\t\treturn;\n+\t}\n+\n+\tmac_stats-\u003eFramesTransmittedOK =\n+\t\tle64_to_cpu(ps-\u003emac_tx_good_pkts);\n+\tmac_stats-\u003eFramesReceivedOK =\n+\t\tle64_to_cpu(ps-\u003emac_rx_good_pkts);\n+\tmac_stats-\u003eFrameCheckSequenceErrors =\n+\t\tle64_to_cpu(ps-\u003emac_rx_fcs_err_pkts);\n+\tmac_stats-\u003eOctetsTransmittedOK =\n+\t\tle64_to_cpu(ps-\u003emac_tx_good_octs);\n+\tmac_stats-\u003eOctetsReceivedOK =\n+\t\tle64_to_cpu(ps-\u003emac_rx_good_octs);\n+\tmac_stats-\u003eMulticastFramesXmittedOK =\n+\t\tle64_to_cpu(ps-\u003emac_tx_multi_pkts);\n+\tmac_stats-\u003eBroadcastFramesXmittedOK =\n+\t\tle64_to_cpu(ps-\u003emac_tx_broad_pkts);\n+\tmac_stats-\u003eMulticastFramesReceivedOK =\n+\t\tle64_to_cpu(ps-\u003emac_rx_multi_pkts);\n+\tmac_stats-\u003eBroadcastFramesReceivedOK =\n+\t\tle64_to_cpu(ps-\u003emac_rx_broad_pkts);\n+\n+\tkfree(ps);\n+}\n+\n+static void hinic3_get_eth_ctrl_stats(struct net_device *netdev,\n+\t\t\t\t      struct ethtool_eth_ctrl_stats *ctrl_stats)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct mag_cmd_port_stats *ps;\n+\tint err;\n+\n+\tif (HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\treturn;\n+\n+\tps = kmalloc_obj(*ps);\n+\tif (!ps)\n+\t\treturn;\n+\n+\terr = hinic3_get_phy_port_stats(nic_dev-\u003ehwdev, ps);\n+\tif (err) {\n+\t\tkfree(ps);\n+\t\tnetdev_err_once(netdev,\n+\t\t\t\t\"Failed to get eth ctrl stats from fw\\n\");\n+\t\treturn;\n+\t}\n+\n+\tctrl_stats-\u003eMACControlFramesTransmitted =\n+\t\tle64_to_cpu(ps-\u003emac_tx_control_pkts);\n+\tctrl_stats-\u003eMACControlFramesReceived =\n+\t\tle64_to_cpu(ps-\u003emac_rx_control_pkts);\n+\n+\tkfree(ps);\n+}\n+\n+static const struct ethtool_rmon_hist_range hinic3_rmon_ranges[] = {\n+\t{     0,    64 },\n+\t{    65,   127 },\n+\t{   128,   255 },\n+\t{   256,   511 },\n+\t{   512,  1023 },\n+\t{  1024,  1518 },\n+\t{  1519,  2047 },\n+\t{  2048,  4095 },\n+\t{  4096,  8191 },\n+\t{  8192,  9216 },\n+\t{  9217, 12287 },\n+\t{}\n+};\n+\n+static void hinic3_get_rmon_stats(struct net_device *netdev,\n+\t\t\t\t  struct ethtool_rmon_stats *rmon_stats,\n+\t\t\t\t  const struct ethtool_rmon_hist_range **ranges)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct mag_cmd_port_stats *ps;\n+\tint err;\n+\n+\tif (HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\tgoto get_rmon_stats_err;\n+\n+\tps = kmalloc_obj(*ps);\n+\tif (!ps)\n+\t\tgoto get_rmon_stats_err;\n+\n+\terr = hinic3_get_phy_port_stats(nic_dev-\u003ehwdev, ps);\n+\tif (err) {\n+\t\tkfree(ps);\n+\t\tnetdev_err_once(netdev,\n+\t\t\t\t\"Failed to get eth rmon stats from fw\\n\");\n+\t\tgoto get_rmon_stats_err;\n+\t}\n+\n+\trmon_stats-\u003eundersize_pkts = le64_to_cpu(ps-\u003emac_rx_undersize_pkts);\n+\trmon_stats-\u003eoversize_pkts  = le64_to_cpu(ps-\u003emac_rx_oversize_pkts);\n+\trmon_stats-\u003efragments      = le64_to_cpu(ps-\u003emac_rx_fragment_pkts);\n+\trmon_stats-\u003ejabbers        = le64_to_cpu(ps-\u003emac_rx_jabber_pkts);\n+\n+\trmon_stats-\u003ehist[0]  = le64_to_cpu(ps-\u003emac_rx_64_oct_pkts);\n+\trmon_stats-\u003ehist[1]  = le64_to_cpu(ps-\u003emac_rx_65_127_oct_pkts);\n+\trmon_stats-\u003ehist[2]  = le64_to_cpu(ps-\u003emac_rx_128_255_oct_pkts);\n+\trmon_stats-\u003ehist[3]  = le64_to_cpu(ps-\u003emac_rx_256_511_oct_pkts);\n+\trmon_stats-\u003ehist[4]  = le64_to_cpu(ps-\u003emac_rx_512_1023_oct_pkts);\n+\trmon_stats-\u003ehist[5]  = le64_to_cpu(ps-\u003emac_rx_1024_1518_oct_pkts);\n+\trmon_stats-\u003ehist[6]  = le64_to_cpu(ps-\u003emac_rx_1519_2047_oct_pkts);\n+\trmon_stats-\u003ehist[7]  = le64_to_cpu(ps-\u003emac_rx_2048_4095_oct_pkts);\n+\trmon_stats-\u003ehist[8]  = le64_to_cpu(ps-\u003emac_rx_4096_8191_oct_pkts);\n+\trmon_stats-\u003ehist[9]  = le64_to_cpu(ps-\u003emac_rx_8192_9216_oct_pkts);\n+\trmon_stats-\u003ehist[10] = le64_to_cpu(ps-\u003emac_rx_9217_12287_oct_pkts);\n+\n+\trmon_stats-\u003ehist_tx[0]  = le64_to_cpu(ps-\u003emac_tx_64_oct_pkts);\n+\trmon_stats-\u003ehist_tx[1]  = le64_to_cpu(ps-\u003emac_tx_65_127_oct_pkts);\n+\trmon_stats-\u003ehist_tx[2]  = le64_to_cpu(ps-\u003emac_tx_128_255_oct_pkts);\n+\trmon_stats-\u003ehist_tx[3]  = le64_to_cpu(ps-\u003emac_tx_256_511_oct_pkts);\n+\trmon_stats-\u003ehist_tx[4]  = le64_to_cpu(ps-\u003emac_tx_512_1023_oct_pkts);\n+\trmon_stats-\u003ehist_tx[5]  = le64_to_cpu(ps-\u003emac_tx_1024_1518_oct_pkts);\n+\trmon_stats-\u003ehist_tx[6]  = le64_to_cpu(ps-\u003emac_tx_1519_2047_oct_pkts);\n+\trmon_stats-\u003ehist_tx[7]  = le64_to_cpu(ps-\u003emac_tx_2048_4095_oct_pkts);\n+\trmon_stats-\u003ehist_tx[8]  = le64_to_cpu(ps-\u003emac_tx_4096_8191_oct_pkts);\n+\trmon_stats-\u003ehist_tx[9]  = le64_to_cpu(ps-\u003emac_tx_8192_9216_oct_pkts);\n+\trmon_stats-\u003ehist_tx[10] = le64_to_cpu(ps-\u003emac_tx_9217_12287_oct_pkts);\n+\n+\t*ranges = hinic3_rmon_ranges;\n+\n+\tkfree(ps);\n+\treturn;\n+\n+get_rmon_stats_err:\n+\t*ranges = NULL;\n+}\n+\n+static void hinic3_get_pause_stats(struct net_device *netdev,\n+\t\t\t\t   struct ethtool_pause_stats *pause_stats)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct mag_cmd_port_stats *ps;\n+\tint err;\n+\n+\tif (HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\treturn;\n+\n+\tps = kmalloc_obj(*ps);\n+\tif (!ps)\n+\t\treturn;\n+\n+\terr = hinic3_get_phy_port_stats(nic_dev-\u003ehwdev, ps);\n+\tif (err) {\n+\t\tkfree(ps);\n+\t\tnetdev_err_once(netdev,\n+\t\t\t\t\"Failed to get eth pause stats from fw\\n\");\n+\t\treturn;\n+\t}\n+\n+\tpause_stats-\u003etx_pause_frames = le64_to_cpu(ps-\u003emac_tx_pause_pkts);\n+\tpause_stats-\u003erx_pause_frames = le64_to_cpu(ps-\u003emac_rx_pause_pkts);\n+\n+\tkfree(ps);\n+}\n+\n+static void hinic3_get_pauseparam(struct net_device *netdev,\n+\t\t\t\t  struct ethtool_pauseparam *pause)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct hinic3_nic_pause_config nic_pause = {};\n+\tint err;\n+\n+\terr = hinic3_get_pause_info(nic_dev, \u0026nic_pause);\n+\tif (err) {\n+\t\tnetdev_err_once(netdev, \"Failed to get pauseparam\\n\");\n+\t} else {\n+\t\tpause-\u003eautoneg = AUTONEG_DISABLE;\n+\t\tpause-\u003erx_pause = nic_pause.rx_pause;\n+\t\tpause-\u003etx_pause = nic_pause.tx_pause;\n+\t}\n+}\n+\n+static int hinic3_set_pauseparam(struct net_device *netdev,\n+\t\t\t\t struct ethtool_pauseparam *pause)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct hinic3_nic_pause_config nic_pause = {};\n+\tint err;\n+\n+\tif (HINIC3_IS_VF(nic_dev-\u003ehwdev))\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (pause-\u003eautoneg)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tnic_pause.rx_pause = (u8)pause-\u003erx_pause;\n+\tnic_pause.tx_pause = (u8)pause-\u003etx_pause;\n+\n+\terr = hinic3_set_pause_info(nic_dev, \u0026nic_pause);\n+\tif (err)\n+\t\tnetdev_err_once(netdev, \"Failed to set pauseparam\\n\");\n+\treturn err;\n+}\n+\n static const struct ethtool_ops hinic3_ethtool_ops = {\n \t.supported_coalesce_params      = ETHTOOL_COALESCE_USECS |\n \t\t\t\t\t  ETHTOOL_COALESCE_PKT_RATE_RX_USECS,\n@@ -417,6 +916,16 @@ static const struct ethtool_ops hinic3_ethtool_ops = {\n \t.get_msglevel                   = hinic3_get_msglevel,\n \t.set_msglevel                   = hinic3_set_msglevel,\n \t.get_link                       = ethtool_op_get_link,\n+\t.get_strings                    = hinic3_get_strings,\n+\t.get_sset_count                 = hinic3_get_sset_count,\n+\t.get_ethtool_stats              = hinic3_get_ethtool_stats,\n+\t.get_eth_phy_stats              = hinic3_get_eth_phy_stats,\n+\t.get_eth_mac_stats              = hinic3_get_eth_mac_stats,\n+\t.get_eth_ctrl_stats             = hinic3_get_eth_ctrl_stats,\n+\t.get_rmon_stats                 = hinic3_get_rmon_stats,\n+\t.get_pause_stats                = hinic3_get_pause_stats,\n+\t.get_pauseparam                 = hinic3_get_pauseparam,\n+\t.set_pauseparam                 = hinic3_set_pauseparam,\n };\n \n void hinic3_set_ethtool_ops(struct net_device *netdev)\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h\nindex cfc9daa3034fe..6b0f486ba590b 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h\n@@ -53,6 +53,17 @@ static inline void mgmt_msg_params_init_default(struct mgmt_msg_params *msg_para\n \tmsg_params-\u003etimeout_ms = 0;\n }\n \n+static inline void\n+mgmt_msg_params_init_in_out(struct mgmt_msg_params *msg_params, void *in_buf,\n+\t\t\t    void *out_buf, u32 in_buf_size, u32 out_buf_size)\n+{\n+\tmsg_params-\u003ebuf_in = in_buf;\n+\tmsg_params-\u003ebuf_out = out_buf;\n+\tmsg_params-\u003ein_size = in_buf_size;\n+\tmsg_params-\u003eexpected_out_size = out_buf_size;\n+\tmsg_params-\u003etimeout_ms = 0;\n+}\n+\n enum cfg_cmd {\n \tCFG_CMD_GET_DEV_CAP = 0,\n };\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h\nindex c5bca3c4af961..a2fe66a40b3ff 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h\n@@ -143,6 +143,41 @@ struct l2nic_cmd_set_dcb_state {\n \tu8                   rsvd[7];\n };\n \n+struct l2nic_port_stats_info {\n+\tstruct mgmt_msg_head msg_head;\n+\tu16                  func_id;\n+\tu16                  rsvd1;\n+};\n+\n+struct l2nic_vport_stats {\n+\t__le64 tx_unicast_pkts_vport;\n+\t__le64 tx_unicast_bytes_vport;\n+\t__le64 tx_multicast_pkts_vport;\n+\t__le64 tx_multicast_bytes_vport;\n+\t__le64 tx_broadcast_pkts_vport;\n+\t__le64 tx_broadcast_bytes_vport;\n+\n+\t__le64 rx_unicast_pkts_vport;\n+\t__le64 rx_unicast_bytes_vport;\n+\t__le64 rx_multicast_pkts_vport;\n+\t__le64 rx_multicast_bytes_vport;\n+\t__le64 rx_broadcast_pkts_vport;\n+\t__le64 rx_broadcast_bytes_vport;\n+\n+\t__le64 tx_discard_vport;\n+\t__le64 rx_discard_vport;\n+\t__le64 tx_err_vport;\n+\t__le64 rx_err_vport;\n+};\n+\n+struct l2nic_cmd_vport_stats {\n+\tstruct mgmt_msg_head     msg_head;\n+\tu32                      stats_size;\n+\tu32                      rsvd1;\n+\tstruct l2nic_vport_stats stats;\n+\tu64                      rsvd2[6];\n+};\n+\n struct l2nic_cmd_lro_config {\n \tstruct mgmt_msg_head msg_head;\n \tu16                  func_id;\n@@ -234,6 +269,7 @@ enum l2nic_cmd {\n \tL2NIC_CMD_SET_VPORT_ENABLE    = 6,\n \tL2NIC_CMD_SET_RX_MODE         = 7,\n \tL2NIC_CMD_SET_SQ_CI_ATTR      = 8,\n+\tL2NIC_CMD_GET_VPORT_STAT      = 9,\n \tL2NIC_CMD_CLEAR_QP_RESOURCE   = 11,\n \tL2NIC_CMD_CFG_RX_LRO          = 13,\n \tL2NIC_CMD_CFG_LRO_TIMER       = 14,\n@@ -272,6 +308,7 @@ enum mag_cmd {\n \tMAG_CMD_SET_PORT_ENABLE = 6,\n \tMAG_CMD_GET_LINK_STATUS = 7,\n \n+\tMAG_CMD_GET_PORT_STAT   = 151,\n \tMAG_CMD_GET_PORT_INFO   = 153,\n };\n \ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c\nindex da73811641a9d..10364c4dc11f9 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c\n@@ -5,6 +5,7 @@\n #include \u003clinux/if_vlan.h\u003e\n #include \u003clinux/netdevice.h\u003e\n #include \u003cnet/vxlan.h\u003e\n+#include \u003cnet/netdev_queues.h\u003e\n \n #include \"hinic3_hwif.h\"\n #include \"hinic3_nic_cfg.h\"\n@@ -802,14 +803,14 @@ static void hinic3_get_stats64(struct net_device *netdev,\n \t\ttxq_stats = \u0026txq-\u003etxq_stats;\n \t\tdo {\n \t\t\tstart = u64_stats_fetch_begin(\u0026txq_stats-\u003esyncp);\n-\t\t\tbytes += txq_stats-\u003ebytes;\n-\t\t\tpackets += txq_stats-\u003epackets;\n-\t\t\tdropped += txq_stats-\u003edropped;\n+\t\t\tbytes = txq_stats-\u003ebytes;\n+\t\t\tpackets = txq_stats-\u003epackets;\n+\t\t\tdropped = txq_stats-\u003edropped;\n \t\t} while (u64_stats_fetch_retry(\u0026txq_stats-\u003esyncp, start));\n+\t\tstats-\u003etx_packets += packets;\n+\t\tstats-\u003etx_bytes   += bytes;\n+\t\tstats-\u003etx_dropped += dropped;\n \t}\n-\tstats-\u003etx_packets = packets;\n-\tstats-\u003etx_bytes   = bytes;\n-\tstats-\u003etx_dropped = dropped;\n \n \tbytes = 0;\n \tpackets = 0;\n@@ -823,17 +824,16 @@ static void hinic3_get_stats64(struct net_device *netdev,\n \t\trxq_stats = \u0026rxq-\u003erxq_stats;\n \t\tdo {\n \t\t\tstart = u64_stats_fetch_begin(\u0026rxq_stats-\u003esyncp);\n-\t\t\tbytes += rxq_stats-\u003ebytes;\n-\t\t\tpackets += rxq_stats-\u003epackets;\n-\t\t\terrors += rxq_stats-\u003ecsum_errors +\n-\t\t\t\trxq_stats-\u003eother_errors;\n-\t\t\tdropped += rxq_stats-\u003edropped;\n+\t\t\tbytes = rxq_stats-\u003ebytes;\n+\t\t\tpackets = rxq_stats-\u003epackets;\n+\t\t\terrors = rxq_stats-\u003eother_errors;\n+\t\t\tdropped = rxq_stats-\u003edropped;\n \t\t} while (u64_stats_fetch_retry(\u0026rxq_stats-\u003esyncp, start));\n+\t\tstats-\u003erx_packets += packets;\n+\t\tstats-\u003erx_bytes   += bytes;\n+\t\tstats-\u003erx_errors  += errors;\n+\t\tstats-\u003erx_dropped += dropped;\n \t}\n-\tstats-\u003erx_packets = packets;\n-\tstats-\u003erx_bytes   = bytes;\n-\tstats-\u003erx_errors  = errors;\n-\tstats-\u003erx_dropped = dropped;\n }\n \n static void hinic3_nic_set_rx_mode(struct net_device *netdev)\n@@ -867,7 +867,80 @@ static const struct net_device_ops hinic3_netdev_ops = {\n \t.ndo_start_xmit       = hinic3_xmit_frame,\n };\n \n+static void hinic3_get_queue_stats_rx(struct net_device *netdev, int i,\n+\t\t\t\t      struct netdev_queue_stats_rx *stats_rx)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct hinic3_rxq_stats *rxq_stats;\n+\tstruct hinic3_rxq *rxq;\n+\tunsigned int start;\n+\n+\trxq = \u0026nic_dev-\u003erxqs[i];\n+\trxq_stats = \u0026rxq-\u003erxq_stats;\n+\tdo {\n+\t\tstart = u64_stats_fetch_begin(\u0026rxq_stats-\u003esyncp);\n+\t\tstats_rx-\u003ebytes = rxq_stats-\u003ebytes;\n+\t\tstats_rx-\u003epackets = rxq_stats-\u003epackets;\n+\t\tstats_rx-\u003ecsum_bad = rxq_stats-\u003ecsum_errors;\n+\t\tstats_rx-\u003ealloc_fail = rxq_stats-\u003ealloc_fail;\n+\t} while (u64_stats_fetch_retry(\u0026rxq_stats-\u003esyncp, start));\n+}\n+\n+static void hinic3_get_queue_stats_tx(struct net_device *netdev, int i,\n+\t\t\t\t      struct netdev_queue_stats_tx *stats_tx)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tstruct hinic3_txq_stats *txq_stats;\n+\tstruct hinic3_txq *txq;\n+\tunsigned int start;\n+\n+\ttxq = \u0026nic_dev-\u003etxqs[i];\n+\ttxq_stats = \u0026txq-\u003etxq_stats;\n+\tdo {\n+\t\tstart = u64_stats_fetch_begin(\u0026txq_stats-\u003esyncp);\n+\t\tstats_tx-\u003ebytes = txq_stats-\u003ebytes;\n+\t\tstats_tx-\u003epackets = txq_stats-\u003epackets;\n+\t\tstats_tx-\u003estop = txq_stats-\u003ebusy;\n+\t} while (u64_stats_fetch_retry(\u0026txq_stats-\u003esyncp, start));\n+}\n+\n+static void hinic3_get_base_stats(struct net_device *netdev,\n+\t\t\t\t  struct netdev_queue_stats_rx *stats_rx,\n+\t\t\t\t  struct netdev_queue_stats_tx *stats_tx)\n+{\n+\tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n+\tint i;\n+\n+\tmemset(stats_rx, 0, sizeof(*stats_rx));\n+\tmemset(stats_tx, 0, sizeof(*stats_tx));\n+\n+\tfor (i = nic_dev-\u003eq_params.num_qps; i \u003c nic_dev-\u003emax_qps; i++) {\n+\t\tstruct netdev_queue_stats_rx rx = {0};\n+\n+\t\thinic3_get_queue_stats_rx(netdev, i, \u0026rx);\n+\t\tstats_rx-\u003ebytes += rx.bytes;\n+\t\tstats_rx-\u003epackets += rx.packets;\n+\t\tstats_rx-\u003ecsum_bad += rx.csum_bad;\n+\t}\n+\n+\tfor (i = nic_dev-\u003eq_params.num_qps; i \u003c nic_dev-\u003emax_qps; i++) {\n+\t\tstruct netdev_queue_stats_tx tx = {0};\n+\n+\t\thinic3_get_queue_stats_tx(netdev, i, \u0026tx);\n+\t\tstats_tx-\u003ebytes += tx.bytes;\n+\t\tstats_tx-\u003epackets += tx.packets;\n+\t\tstats_tx-\u003estop += tx.stop;\n+\t}\n+}\n+\n+static const struct netdev_stat_ops hinic3_stat_ops = {\n+\t.get_queue_stats_rx  = hinic3_get_queue_stats_rx,\n+\t.get_queue_stats_tx  = hinic3_get_queue_stats_tx,\n+\t.get_base_stats      = hinic3_get_base_stats,\n+};\n+\n void hinic3_set_netdev_ops(struct net_device *netdev)\n {\n \tnetdev-\u003enetdev_ops = \u0026hinic3_netdev_ops;\n+\tnetdev-\u003estat_ops = \u0026hinic3_stat_ops;\n }\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c\nindex de5a7984d2cb9..b5c696fe6cdfa 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c\n@@ -738,3 +738,74 @@ int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev,\n \treturn hinic3_cfg_hw_pause(nic_dev-\u003ehwdev, MGMT_MSG_CMD_OP_GET,\n \t\t\t\t   nic_pause);\n }\n+\n+int hinic3_set_pause_info(struct hinic3_nic_dev *nic_dev,\n+\t\t\t  struct hinic3_nic_pause_config *nic_pause)\n+{\n+\treturn hinic3_cfg_hw_pause(nic_dev-\u003ehwdev, MGMT_MSG_CMD_OP_SET,\n+\t\t\t\t   nic_pause);\n+}\n+\n+int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id,\n+\t\t\t   struct l2nic_vport_stats *stats)\n+{\n+\tstruct l2nic_cmd_vport_stats vport_stats = {};\n+\tstruct l2nic_port_stats_info stats_info = {};\n+\tstruct mgmt_msg_params msg_params = {};\n+\tint err;\n+\n+\tstats_info.func_id = func_id;\n+\n+\tmgmt_msg_params_init_in_out(\u0026msg_params, \u0026stats_info, \u0026vport_stats,\n+\t\t\t\t    sizeof(stats_info), sizeof(vport_stats));\n+\n+\terr = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,\n+\t\t\t\t       L2NIC_CMD_GET_VPORT_STAT, \u0026msg_params);\n+\n+\tif (err || vport_stats.msg_head.status) {\n+\t\tdev_err_once(hwdev-\u003edev,\n+\t\t\t     \"Failed to get function statistics, err: %d, status: 0x%x\\n\",\n+\t\t\t     err, vport_stats.msg_head.status);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tmemcpy(stats, \u0026vport_stats.stats, sizeof(*stats));\n+\n+\treturn 0;\n+}\n+\n+int hinic3_get_phy_port_stats(struct hinic3_hwdev *hwdev,\n+\t\t\t      struct mag_cmd_port_stats *stats)\n+{\n+\tstruct mag_cmd_get_port_stats_in ps_in = {};\n+\tstruct mag_cmd_get_port_stats_out *ps_out;\n+\tstruct mgmt_msg_params msg_params = {};\n+\tint err;\n+\n+\tps_out = kzalloc_obj(*ps_out);\n+\tif (!ps_out)\n+\t\treturn -ENOMEM;\n+\n+\tps_in.port_id = hinic3_physical_port_id(hwdev);\n+\n+\tmgmt_msg_params_init_in_out(\u0026msg_params, \u0026ps_in, ps_out,\n+\t\t\t\t    sizeof(ps_in), sizeof(*ps_out));\n+\n+\terr = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK,\n+\t\t\t\t       MAG_CMD_GET_PORT_STAT, \u0026msg_params);\n+\n+\tif (err || ps_out-\u003ehead.status) {\n+\t\tdev_err_once(hwdev-\u003edev,\n+\t\t\t     \"Failed to get port statistics, err: %d, status: 0x%x\\n\",\n+\t\t\t     err, ps_out-\u003ehead.status);\n+\t\terr = -EFAULT;\n+\t\tgoto out;\n+\t}\n+\n+\tmemcpy(stats, \u0026ps_out-\u003ecounter, sizeof(*stats));\n+\n+out:\n+\tkfree(ps_out);\n+\n+\treturn err;\n+}\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h\nindex 5d52202a8d4eb..beb491d667380 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h\n@@ -129,6 +129,110 @@ struct mag_cmd_get_xsfp_present {\n \tu8                   rsvd[2];\n };\n \n+struct mag_cmd_port_stats {\n+\t__le64 mac_tx_fragment_pkts;\n+\t__le64 mac_tx_undersize_pkts;\n+\t__le64 mac_tx_undermin_pkts;\n+\t__le64 mac_tx_64_oct_pkts;\n+\t__le64 mac_tx_65_127_oct_pkts;\n+\t__le64 mac_tx_128_255_oct_pkts;\n+\t__le64 mac_tx_256_511_oct_pkts;\n+\t__le64 mac_tx_512_1023_oct_pkts;\n+\t__le64 mac_tx_1024_1518_oct_pkts;\n+\t__le64 mac_tx_1519_2047_oct_pkts;\n+\t__le64 mac_tx_2048_4095_oct_pkts;\n+\t__le64 mac_tx_4096_8191_oct_pkts;\n+\t__le64 mac_tx_8192_9216_oct_pkts;\n+\t__le64 mac_tx_9217_12287_oct_pkts;\n+\t__le64 mac_tx_12288_16383_oct_pkts;\n+\t__le64 mac_tx_jumbo_bad_pkts;\n+\t__le64 mac_tx_jumbo_good_pkts;\n+\t__le64 mac_tx_oversize_pkts;\n+\t__le64 mac_tx_jabber_pkts;\n+\t__le64 mac_tx_bad_pkts;\n+\t__le64 mac_tx_bad_octs;\n+\t__le64 mac_tx_good_pkts;\n+\t__le64 mac_tx_good_octs;\n+\t__le64 mac_tx_total_pkts;\n+\t__le64 mac_tx_total_octs;\n+\t__le64 mac_tx_uni_pkts;\n+\t__le64 mac_tx_multi_pkts;\n+\t__le64 mac_tx_broad_pkts;\n+\t__le64 mac_tx_pause_pkts;\n+\t__le64 mac_tx_pfc_pkts;\n+\t__le64 mac_tx_pfc_pri0_pkts;\n+\t__le64 mac_tx_pfc_pri1_pkts;\n+\t__le64 mac_tx_pfc_pri2_pkts;\n+\t__le64 mac_tx_pfc_pri3_pkts;\n+\t__le64 mac_tx_pfc_pri4_pkts;\n+\t__le64 mac_tx_pfc_pri5_pkts;\n+\t__le64 mac_tx_pfc_pri6_pkts;\n+\t__le64 mac_tx_pfc_pri7_pkts;\n+\t__le64 mac_tx_control_pkts;\n+\t__le64 mac_tx_err_all_pkts;\n+\t__le64 mac_tx_from_app_good_pkts;\n+\t__le64 mac_tx_from_app_bad_pkts;\n+\n+\t__le64 mac_rx_fragment_pkts;\n+\t__le64 mac_rx_undersize_pkts;\n+\t__le64 mac_rx_undermin_pkts;\n+\t__le64 mac_rx_64_oct_pkts;\n+\t__le64 mac_rx_65_127_oct_pkts;\n+\t__le64 mac_rx_128_255_oct_pkts;\n+\t__le64 mac_rx_256_511_oct_pkts;\n+\t__le64 mac_rx_512_1023_oct_pkts;\n+\t__le64 mac_rx_1024_1518_oct_pkts;\n+\t__le64 mac_rx_1519_2047_oct_pkts;\n+\t__le64 mac_rx_2048_4095_oct_pkts;\n+\t__le64 mac_rx_4096_8191_oct_pkts;\n+\t__le64 mac_rx_8192_9216_oct_pkts;\n+\t__le64 mac_rx_9217_12287_oct_pkts;\n+\t__le64 mac_rx_12288_16383_oct_pkts;\n+\t__le64 mac_rx_jumbo_bad_pkts;\n+\t__le64 mac_rx_jumbo_good_pkts;\n+\t__le64 mac_rx_oversize_pkts;\n+\t__le64 mac_rx_jabber_pkts;\n+\t__le64 mac_rx_bad_pkts;\n+\t__le64 mac_rx_bad_octs;\n+\t__le64 mac_rx_good_pkts;\n+\t__le64 mac_rx_good_octs;\n+\t__le64 mac_rx_total_pkts;\n+\t__le64 mac_rx_total_octs;\n+\t__le64 mac_rx_uni_pkts;\n+\t__le64 mac_rx_multi_pkts;\n+\t__le64 mac_rx_broad_pkts;\n+\t__le64 mac_rx_pause_pkts;\n+\t__le64 mac_rx_pfc_pkts;\n+\t__le64 mac_rx_pfc_pri0_pkts;\n+\t__le64 mac_rx_pfc_pri1_pkts;\n+\t__le64 mac_rx_pfc_pri2_pkts;\n+\t__le64 mac_rx_pfc_pri3_pkts;\n+\t__le64 mac_rx_pfc_pri4_pkts;\n+\t__le64 mac_rx_pfc_pri5_pkts;\n+\t__le64 mac_rx_pfc_pri6_pkts;\n+\t__le64 mac_rx_pfc_pri7_pkts;\n+\t__le64 mac_rx_control_pkts;\n+\t__le64 mac_rx_sym_err_pkts;\n+\t__le64 mac_rx_fcs_err_pkts;\n+\t__le64 mac_rx_send_app_good_pkts;\n+\t__le64 mac_rx_send_app_bad_pkts;\n+\t__le64 mac_rx_unfilter_pkts;\n+};\n+\n+struct mag_cmd_get_port_stats_in {\n+\tstruct mgmt_msg_head head;\n+\n+\tu8                   port_id;\n+\tu8                   rsvd0[3];\n+};\n+\n+struct mag_cmd_get_port_stats_out {\n+\tstruct mgmt_msg_head      head;\n+\n+\tstruct mag_cmd_port_stats counter;\n+\tu64                       rsvd1[15];\n+};\n+\n enum link_err_type {\n \tLINK_ERR_MODULE_UNRECOGENIZED,\n \tLINK_ERR_NUM,\n@@ -214,5 +318,11 @@ int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id);\n \n int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev,\n \t\t\t  struct hinic3_nic_pause_config *nic_pause);\n+int hinic3_set_pause_info(struct hinic3_nic_dev *nic_dev,\n+\t\t\t  struct hinic3_nic_pause_config *nic_pause);\n \n+int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id,\n+\t\t\t   struct l2nic_vport_stats *stats);\n+int hinic3_get_phy_port_stats(struct hinic3_hwdev *hwdev,\n+\t\t\t      struct mag_cmd_port_stats *stats);\n #endif\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c\nindex 309ab59013797..ae4ccff4a09a9 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c\n@@ -43,10 +43,7 @@ static void hinic3_rxq_clean_stats(struct hinic3_rxq_stats *rxq_stats)\n \trxq_stats-\u003eother_errors = 0;\n \trxq_stats-\u003edropped = 0;\n \trxq_stats-\u003erx_buf_empty = 0;\n-\n-\trxq_stats-\u003ealloc_skb_err = 0;\n-\trxq_stats-\u003ealloc_rx_buf_err = 0;\n-\trxq_stats-\u003erestore_drop_sge = 0;\n+\trxq_stats-\u003ealloc_fail = 0;\n \tu64_stats_update_end(\u0026rxq_stats-\u003esyncp);\n }\n \n@@ -147,6 +144,8 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)\n {\n \tu32 i, free_wqebbs = rxq-\u003edelta - 1;\n \tstruct hinic3_rx_info *rx_info;\n+\tstruct u64_stats_sync *syncp;\n+\tunsigned long flags;\n \tdma_addr_t dma_addr;\n \tint err;\n \n@@ -155,8 +154,13 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)\n \n \t\terr = rx_alloc_mapped_page(rxq-\u003epage_pool, rx_info,\n \t\t\t\t\t   rxq-\u003ebuf_len);\n-\t\tif (unlikely(err))\n+\t\tif (unlikely(err)) {\n+\t\t\tsyncp = \u0026rxq-\u003erxq_stats.syncp;\n+\t\t\tflags = u64_stats_update_begin_irqsave(syncp);\n+\t\t\trxq-\u003erxq_stats.alloc_fail++;\n+\t\t\tu64_stats_update_end_irqrestore(syncp, flags);\n \t\t\tbreak;\n+\t\t}\n \n \t\tdma_addr = page_pool_get_dma_addr(rx_info-\u003epage) +\n \t\t\trx_info-\u003epage_offset;\n@@ -170,6 +174,11 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)\n \t\t\t\trxq-\u003enext_to_update \u003c\u003c HINIC3_NORMAL_RQ_WQE);\n \t\trxq-\u003edelta -= i;\n \t\trxq-\u003enext_to_alloc = rxq-\u003enext_to_update;\n+\t} else if (free_wqebbs == rxq-\u003eq_depth - 1) {\n+\t\tsyncp = \u0026rxq-\u003erxq_stats.syncp;\n+\t\tflags = u64_stats_update_begin_irqsave(syncp);\n+\t\trxq-\u003erxq_stats.rx_buf_empty++;\n+\t\tu64_stats_update_end_irqrestore(syncp, flags);\n \t}\n \n \treturn i;\n@@ -330,10 +339,23 @@ static void hinic3_rx_csum(struct hinic3_rxq *rxq, u32 offload_type,\n \tstruct net_device *netdev = rxq-\u003enetdev;\n \tbool l2_tunnel;\n \n+\t/* HW ensures that only 1 bit is set in csum_err. */\n+\tif (unlikely(csum_err == HINIC3_RX_CSUM_IPSU_OTHER_ERR)) {\n+\t\tu64_stats_update_begin(\u0026rxq-\u003erxq_stats.syncp);\n+\t\trxq-\u003erxq_stats.other_errors++;\n+\t\tu64_stats_update_end(\u0026rxq-\u003erxq_stats.syncp);\n+\t}\n+\n \tif (!(netdev-\u003efeatures \u0026 NETIF_F_RXCSUM))\n \t\treturn;\n \n \tif (unlikely(csum_err)) {\n+\t\tif (csum_err != HINIC3_RX_CSUM_HW_CHECK_NONE \u0026\u0026\n+\t\t    csum_err != HINIC3_RX_CSUM_IPSU_OTHER_ERR) {\n+\t\t\tu64_stats_update_begin(\u0026rxq-\u003erxq_stats.syncp);\n+\t\t\trxq-\u003erxq_stats.csum_errors++;\n+\t\t\tu64_stats_update_end(\u0026rxq-\u003erxq_stats.syncp);\n+\t\t}\n \t\t/* pkt type is recognized by HW, and csum is wrong */\n \t\tskb-\u003eip_summed = CHECKSUM_NONE;\n \t\treturn;\n@@ -387,8 +409,12 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_rq_cqe *rx_cqe,\n \tu16 num_lro;\n \n \tskb = hinic3_fetch_rx_buffer(rxq, pkt_len);\n-\tif (unlikely(!skb))\n+\tif (unlikely(!skb)) {\n+\t\tu64_stats_update_begin(\u0026rxq-\u003erxq_stats.syncp);\n+\t\trxq-\u003erxq_stats.alloc_fail++;\n+\t\tu64_stats_update_end(\u0026rxq-\u003erxq_stats.syncp);\n \t\treturn -ENOMEM;\n+\t}\n \n \t/* place header in linear portion of buffer */\n \tif (skb_is_nonlinear(skb))\n@@ -555,6 +581,7 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)\n \tstruct hinic3_nic_dev *nic_dev = netdev_priv(rxq-\u003enetdev);\n \tu32 sw_ci, status, pkt_len, vlan_len;\n \tstruct hinic3_rq_cqe *rx_cqe;\n+\tu64 rx_bytes = 0;\n \tu32 num_wqe = 0;\n \tint nr_pkts = 0;\n \tu16 num_lro;\n@@ -575,6 +602,7 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)\n \t\t\tbreak;\n \n \t\tnr_pkts++;\n+\t\trx_bytes += pkt_len;\n \t\tnum_lro = RQ_CQE_STATUS_GET(status, NUM_LRO);\n \t\tif (num_lro)\n \t\t\tnum_wqe += hinic3_get_sge_num(rxq, pkt_len);\n@@ -588,5 +616,24 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)\n \tif (rxq-\u003edelta \u003e= HINIC3_RX_BUFFER_WRITE)\n \t\thinic3_rx_fill_buffers(rxq);\n \n+\tu64_stats_update_begin(\u0026rxq-\u003erxq_stats.syncp);\n+\trxq-\u003erxq_stats.packets += (u64)nr_pkts;\n+\trxq-\u003erxq_stats.bytes += rx_bytes;\n+\tu64_stats_update_end(\u0026rxq-\u003erxq_stats.syncp);\n \treturn nr_pkts;\n }\n+\n+void hinic3_rxq_get_stats(struct hinic3_rxq *rxq,\n+\t\t\t  struct hinic3_rxq_stats *stats)\n+{\n+\tstruct hinic3_rxq_stats *rxq_stats = \u0026rxq-\u003erxq_stats;\n+\tunsigned int start;\n+\n+\tdo {\n+\t\tstart = u64_stats_fetch_begin(\u0026rxq_stats-\u003esyncp);\n+\t\tstats-\u003ecsum_errors = rxq_stats-\u003ecsum_errors;\n+\t\tstats-\u003eother_errors = rxq_stats-\u003eother_errors;\n+\t\tstats-\u003erx_buf_empty = rxq_stats-\u003erx_buf_empty;\n+\t\tstats-\u003ealloc_fail = rxq_stats-\u003ealloc_fail;\n+\t} while (u64_stats_fetch_retry(\u0026rxq_stats-\u003esyncp, start));\n+}\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h\nindex 06d1b3299e7cf..a54184beedc9f 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h\n@@ -8,6 +8,10 @@\n #include \u003clinux/dim.h\u003e\n #include \u003clinux/netdevice.h\u003e\n \n+/* rx cqe checksum err */\n+#define HINIC3_RX_CSUM_HW_CHECK_NONE    BIT(7)\n+#define HINIC3_RX_CSUM_IPSU_OTHER_ERR   BIT(8)\n+\n #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK           GENMASK(4, 0)\n #define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK            GENMASK(6, 5)\n #define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK  GENMASK(11, 8)\n@@ -37,9 +41,7 @@ struct hinic3_rxq_stats {\n \tu64                   other_errors;\n \tu64                   dropped;\n \tu64                   rx_buf_empty;\n-\tu64                   alloc_skb_err;\n-\tu64                   alloc_rx_buf_err;\n-\tu64                   restore_drop_sge;\n+\tu64                   alloc_fail;\n \tstruct u64_stats_sync syncp;\n };\n \n@@ -125,4 +127,6 @@ int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq,\n \t\t\t  u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res);\n int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget);\n \n+void hinic3_rxq_get_stats(struct hinic3_rxq *rxq,\n+\t\t\t  struct hinic3_rxq_stats *stats);\n #endif\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c\nindex f92568f0f00b7..b0a0ffb1052b3 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c\n@@ -25,11 +25,9 @@ static void hinic3_txq_clean_stats(struct hinic3_txq_stats *txq_stats)\n \ttxq_stats-\u003edropped = 0;\n \n \ttxq_stats-\u003eskb_pad_err = 0;\n-\ttxq_stats-\u003efrag_len_overflow = 0;\n \ttxq_stats-\u003eoffload_cow_skb_err = 0;\n \ttxq_stats-\u003emap_frag_err = 0;\n \ttxq_stats-\u003eunknown_tunnel_pkt = 0;\n-\ttxq_stats-\u003efrag_size_err = 0;\n \tu64_stats_update_end(\u0026txq_stats-\u003esyncp);\n }\n \n@@ -97,8 +95,12 @@ static int hinic3_tx_map_skb(struct net_device *netdev, struct sk_buff *skb,\n \n \tdma_info[0].dma = dma_map_single(\u0026pdev-\u003edev, skb-\u003edata,\n \t\t\t\t\t skb_headlen(skb), DMA_TO_DEVICE);\n-\tif (dma_mapping_error(\u0026pdev-\u003edev, dma_info[0].dma))\n+\tif (dma_mapping_error(\u0026pdev-\u003edev, dma_info[0].dma)) {\n+\t\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\t\ttxq-\u003etxq_stats.map_frag_err++;\n+\t\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \t\treturn -EFAULT;\n+\t}\n \n \tdma_info[0].len = skb_headlen(skb);\n \n@@ -117,6 +119,9 @@ static int hinic3_tx_map_skb(struct net_device *netdev, struct sk_buff *skb,\n \t\t\t\t\t\t     skb_frag_size(frag),\n \t\t\t\t\t\t     DMA_TO_DEVICE);\n \t\tif (dma_mapping_error(\u0026pdev-\u003edev, dma_info[idx].dma)) {\n+\t\t\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\t\t\ttxq-\u003etxq_stats.map_frag_err++;\n+\t\t\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \t\t\terr = -EFAULT;\n \t\t\tgoto err_unmap_page;\n \t\t}\n@@ -260,6 +265,9 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct hinic3_sq_task *task,\n \t\tif (l4_proto != IPPROTO_UDP ||\n \t\t    ((struct udphdr *)skb_transport_header(skb))-\u003edest !=\n \t\t    VXLAN_OFFLOAD_PORT_LE) {\n+\t\t\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\t\t\ttxq-\u003etxq_stats.unknown_tunnel_pkt++;\n+\t\t\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \t\t\t/* Unsupported tunnel packet, disable csum offload */\n \t\t\treturn skb_checksum_help(skb);\n \t\t}\n@@ -541,8 +549,12 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,\n \tu32 offload;\n \tint err;\n \n-\tif (skb_put_padto(skb, MIN_SKB_LEN))\n+\tif (skb_put_padto(skb, MIN_SKB_LEN)) {\n+\t\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\t\ttxq-\u003etxq_stats.skb_pad_err++;\n+\t\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \t\tgoto err_out;\n+\t}\n \n \toffload = hinic3_tx_offload(skb, \u0026task, \u0026queue_info, txq);\n \tnum_sge = skb_shinfo(skb)-\u003enr_frags + 1;\n@@ -557,10 +569,16 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,\n \t\t\t\t\thinic3_wq_free_wqebbs(\u0026txq-\u003esq-\u003ewq),\n \t\t\t\t\ttxq-\u003etx_start_thrs);\n \n+\t\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\t\ttxq-\u003etxq_stats.busy++;\n+\t\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \t\treturn NETDEV_TX_BUSY;\n \t}\n \n \tif (unlikely(offload == HINIC3_TX_OFFLOAD_INVALID)) {\n+\t\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\t\ttxq-\u003etxq_stats.offload_cow_skb_err++;\n+\t\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \t\tgoto err_drop_pkt;\n \t} else if (!offload) {\n \t\twqebb_cnt -= 1;\n@@ -599,11 +617,19 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,\n \thinic3_write_db(txq-\u003esq, 0, DB_CFLAG_DP_SQ,\n \t\t\thinic3_get_sq_local_pi(txq-\u003esq));\n \n+\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\ttxq-\u003etxq_stats.bytes += skb-\u003elen;\n+\ttxq-\u003etxq_stats.packets += 1;\n+\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n+\n \treturn NETDEV_TX_OK;\n \n err_drop_pkt:\n \tdev_kfree_skb_any(skb);\n err_out:\n+\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\ttxq-\u003etxq_stats.dropped++;\n+\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \treturn NETDEV_TX_OK;\n }\n \n@@ -611,18 +637,25 @@ netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)\n {\n \tstruct hinic3_nic_dev *nic_dev = netdev_priv(netdev);\n \tu16 q_id = skb_get_queue_mapping(skb);\n-\n-\tif (unlikely(!netif_carrier_ok(netdev)))\n-\t\tgoto err_drop_pkt;\n+\tstruct hinic3_txq *txq;\n \n \tif (unlikely(q_id \u003e= nic_dev-\u003eq_params.num_qps))\n+\t\tgoto err_qid_out;\n+\n+\ttxq = \u0026nic_dev-\u003etxqs[q_id];\n+\n+\tif (unlikely(!netif_carrier_ok(netdev)))\n \t\tgoto err_drop_pkt;\n \n-\treturn hinic3_send_one_skb(skb, netdev, \u0026nic_dev-\u003etxqs[q_id]);\n+\treturn hinic3_send_one_skb(skb, netdev, txq);\n \n err_drop_pkt:\n-\tdev_kfree_skb_any(skb);\n+\tu64_stats_update_begin(\u0026txq-\u003etxq_stats.syncp);\n+\ttxq-\u003etxq_stats.dropped++;\n+\tu64_stats_update_end(\u0026txq-\u003etxq_stats.syncp);\n \n+err_qid_out:\n+\tdev_kfree_skb_any(skb);\n \treturn NETDEV_TX_OK;\n }\n \n@@ -795,3 +828,19 @@ bool hinic3_tx_poll(struct hinic3_txq *txq, int budget)\n \n \treturn pkts == HINIC3_TX_POLL_WEIGHT;\n }\n+\n+void hinic3_txq_get_stats(struct hinic3_txq *txq,\n+\t\t\t  struct hinic3_txq_stats *stats)\n+{\n+\tstruct hinic3_txq_stats *txq_stats = \u0026txq-\u003etxq_stats;\n+\tunsigned int start;\n+\n+\tdo {\n+\t\tstart = u64_stats_fetch_begin(\u0026txq_stats-\u003esyncp);\n+\t\tstats-\u003ebusy = txq_stats-\u003ebusy;\n+\t\tstats-\u003eskb_pad_err = txq_stats-\u003eskb_pad_err;\n+\t\tstats-\u003eoffload_cow_skb_err = txq_stats-\u003eoffload_cow_skb_err;\n+\t\tstats-\u003emap_frag_err = txq_stats-\u003emap_frag_err;\n+\t\tstats-\u003eunknown_tunnel_pkt = txq_stats-\u003eunknown_tunnel_pkt;\n+\t} while (u64_stats_fetch_retry(\u0026txq_stats-\u003esyncp, start));\n+}\ndiff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h\nindex 00194f2a1bcc1..9e429362b9363 100644\n--- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h\n+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h\n@@ -106,11 +106,9 @@ struct hinic3_txq_stats {\n \tu64                   busy;\n \tu64                   dropped;\n \tu64                   skb_pad_err;\n-\tu64                   frag_len_overflow;\n \tu64                   offload_cow_skb_err;\n \tu64                   map_frag_err;\n \tu64                   unknown_tunnel_pkt;\n-\tu64                   frag_size_err;\n \tstruct u64_stats_sync syncp;\n };\n \n@@ -160,4 +158,6 @@ netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netdev);\n bool hinic3_tx_poll(struct hinic3_txq *txq, int budget);\n void hinic3_flush_txqs(struct net_device *netdev);\n \n+void hinic3_txq_get_stats(struct hinic3_txq *txq,\n+\t\t\t  struct hinic3_txq_stats *stats);\n #endif\n"
}

2/1 2026/10/22 23:07 agent patch-evaluator
0m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The changes in this patch series are entirely confined to the Huawei HiNIC3 driver (drivers/net/ethernet/huawei/hinic3/), which is a vendor-specific Ethernet PCIe driver for Huawei SmartNIC hardware. This driver requires proprietary physical PCIe ASIC hardware (Huawei PCI vendor ID 0x19e5, device IDs 0x0222 and 0x375f) that is not emulated in standard virtualized environments (QEMU or GCE). Consequently, the modified code is structurally unreachable for fuzzing.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 490853b8fa97d00ec9df421558110d4e58e27a7f
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Oct 22 23:07:25 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
index 90fc16288de95..3005441056f92 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
@@ -13,8 +13,11 @@
 
 #include "hinic3_lld.h"
 #include "hinic3_hw_comm.h"
+#include "hinic3_hwif.h"
 #include "hinic3_nic_dev.h"
 #include "hinic3_nic_cfg.h"
+#include "hinic3_tx.h"
+#include "hinic3_rx.h"
 
 #define HINIC3_MGMT_VERSION_MAX_LEN     32
 
@@ -409,6 +412,502 @@ hinic3_get_link_ksettings(struct net_device *netdev,
 	return 0;
 }
 
+struct hinic3_stats {
+	char name[ETH_GSTRING_LEN];
+	int  offset;
+};
+
+#define HINIC3_STAT_SIZE_CHECK(type, member) \
+	BUILD_BUG_ON_ZERO(sizeof_field(type, member) != sizeof(u64))
+
+#define HINIC3_FUNC_STAT(_stat_item) {	\
+	.name   = #_stat_item, \
+	.offset = offsetof(struct l2nic_vport_stats, _stat_item) \
+		  + 0 * HINIC3_STAT_SIZE_CHECK(struct l2nic_vport_stats, \
+					       _stat_item) \
+}
+
+static struct hinic3_stats hinic3_function_stats[] = {
+	HINIC3_FUNC_STAT(tx_unicast_pkts_vport),
+	HINIC3_FUNC_STAT(tx_unicast_bytes_vport),
+	HINIC3_FUNC_STAT(tx_broadcast_pkts_vport),
+	HINIC3_FUNC_STAT(tx_broadcast_bytes_vport),
+
+	HINIC3_FUNC_STAT(rx_unicast_pkts_vport),
+	HINIC3_FUNC_STAT(rx_unicast_bytes_vport),
+	HINIC3_FUNC_STAT(rx_broadcast_pkts_vport),
+	HINIC3_FUNC_STAT(rx_broadcast_bytes_vport),
+};
+
+#define HINIC3_PORT_STAT(_stat_item) { \
+	.name   = #_stat_item, \
+	.offset = offsetof(struct mag_cmd_port_stats, _stat_item) \
+		  + 0 * HINIC3_STAT_SIZE_CHECK(struct mag_cmd_port_stats, \
+					       _stat_item) \
+}
+
+static struct hinic3_stats hinic3_port_stats[] = {
+	HINIC3_PORT_STAT(mac_tx_fragment_pkts),
+	HINIC3_PORT_STAT(mac_tx_undersize_pkts),
+	HINIC3_PORT_STAT(mac_tx_undermin_pkts),
+	HINIC3_PORT_STAT(mac_tx_jumbo_bad_pkts),
+	HINIC3_PORT_STAT(mac_tx_jumbo_good_pkts),
+	HINIC3_PORT_STAT(mac_tx_oversize_pkts),
+	HINIC3_PORT_STAT(mac_tx_jabber_pkts),
+	HINIC3_PORT_STAT(mac_tx_bad_pkts),
+	HINIC3_PORT_STAT(mac_tx_bad_octs),
+	HINIC3_PORT_STAT(mac_tx_total_pkts),
+	HINIC3_PORT_STAT(mac_tx_uni_pkts),
+	HINIC3_PORT_STAT(mac_tx_err_all_pkts),
+	HINIC3_PORT_STAT(mac_tx_from_app_good_pkts),
+	HINIC3_PORT_STAT(mac_tx_from_app_bad_pkts),
+
+	HINIC3_PORT_STAT(mac_rx_undermin_pkts),
+	HINIC3_PORT_STAT(mac_rx_jumbo_bad_pkts),
+	HINIC3_PORT_STAT(mac_rx_jumbo_good_pkts),
+	HINIC3_PORT_STAT(mac_rx_bad_pkts),
+	HINIC3_PORT_STAT(mac_rx_bad_octs),
+	HINIC3_PORT_STAT(mac_rx_total_pkts),
+	HINIC3_PORT_STAT(mac_rx_uni_pkts),
+	HINIC3_PORT_STAT(mac_rx_send_app_good_pkts),
+	HINIC3_PORT_STAT(mac_rx_send_app_bad_pkts),
+	HINIC3_PORT_STAT(mac_rx_unfilter_pkts),
+};
+
+#define HINIC3_TXQ_STAT(_stat_item) { \
+	.name   = "txq%d_"#_stat_item, \
+	.offset = offsetof(struct hinic3_txq_stats, _stat_item) \
+		  + 0 * HINIC3_STAT_SIZE_CHECK(struct hinic3_txq_stats, \
+					       _stat_item) \
+}
+
+#define HINIC3_RXQ_STAT(_stat_item) { \
+	.name   = "rxq%d_"#_stat_item, \
+	.offset = offsetof(struct hinic3_rxq_stats, _stat_item) \
+		  + 0 * HINIC3_STAT_SIZE_CHECK(struct hinic3_rxq_stats, \
+					       _stat_item) \
+}
+
+static struct hinic3_stats hinic3_tx_queue_stats[] = {
+	HINIC3_TXQ_STAT(skb_pad_err),
+	HINIC3_TXQ_STAT(offload_cow_skb_err),
+	HINIC3_TXQ_STAT(map_frag_err),
+	HINIC3_TXQ_STAT(unknown_tunnel_pkt),
+};
+
+static struct hinic3_stats hinic3_rx_queue_stats[] = {
+	HINIC3_RXQ_STAT(other_errors),
+	HINIC3_RXQ_STAT(rx_buf_empty),
+};
+
+static u16 hinic3_get_hw_stats_strings(struct hinic3_nic_dev *nic_dev, u8 *p)
+{
+	u16 i, cnt = 0;
+
+	for (i = 0; i < ARRAY_SIZE(hinic3_function_stats); i++) {
+		ethtool_puts(&p, hinic3_function_stats[i].name);
+		cnt++;
+	}
+
+	if (!HINIC3_IS_VF(nic_dev->hwdev)) {
+		for (i = 0; i < ARRAY_SIZE(hinic3_port_stats); i++) {
+			ethtool_puts(&p, hinic3_port_stats[i].name);
+			cnt++;
+		}
+	}
+
+	return cnt;
+}
+
+static void hinic3_get_qp_stats_strings(struct hinic3_nic_dev *nic_dev, u8 *p)
+{
+	u16 i, j;
+
+	for (i = 0; i < nic_dev->q_params.num_qps; i++) {
+		for (j = 0; j < ARRAY_SIZE(hinic3_tx_queue_stats); j++)
+			ethtool_sprintf(&p,
+					hinic3_tx_queue_stats[j].name, i);
+	}
+
+	for (i = 0; i < nic_dev->q_params.num_qps; i++) {
+		for (j = 0; j < ARRAY_SIZE(hinic3_rx_queue_stats); j++)
+			ethtool_sprintf(&p,
+					hinic3_rx_queue_stats[j].name, i);
+	}
+}
+
+static void hinic3_get_strings(struct net_device *netdev,
+			       u32 stringset, u8 *data)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	u16 offset;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		offset = hinic3_get_hw_stats_strings(nic_dev, data);
+		hinic3_get_qp_stats_strings(nic_dev,
+					    data + offset * ETH_GSTRING_LEN);
+
+		break;
+	}
+}
+
+static int hinic3_get_sset_count(struct net_device *netdev, int sset)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	int count, q_num;
+
+	switch (sset) {
+	case ETH_SS_STATS:
+		q_num = nic_dev->q_params.num_qps;
+		count = ARRAY_SIZE(hinic3_function_stats) +
+			(ARRAY_SIZE(hinic3_tx_queue_stats) +
+			 ARRAY_SIZE(hinic3_rx_queue_stats)) *
+			q_num;
+
+		if (!HINIC3_IS_VF(nic_dev->hwdev))
+			count += ARRAY_SIZE(hinic3_port_stats);
+
+		return count;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static u16 hinic3_get_ethtool_port_stats(struct net_device *netdev, u64 *data)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct mag_cmd_port_stats *ps;
+	u16 i = 0, j;
+	char *p;
+	int err;
+
+	ps = kmalloc_obj(*ps);
+	if (!ps)
+		goto err_zero_stats;
+
+	err = hinic3_get_phy_port_stats(nic_dev->hwdev, ps);
+	if (err) {
+		kfree(ps);
+		netdev_err_once(netdev, "Failed to get port stats from fw\n");
+		goto err_zero_stats;
+	}
+
+	for (j = 0; j < ARRAY_SIZE(hinic3_port_stats); j++, i++) {
+		p = (char *)ps + hinic3_port_stats[j].offset;
+		data[i] = le64_to_cpu(*(__le64 *)p);
+	}
+
+	kfree(ps);
+
+	return i;
+
+err_zero_stats:
+	memset(&data[i], 0, ARRAY_SIZE(hinic3_port_stats) * sizeof(*data));
+
+	return i + ARRAY_SIZE(hinic3_port_stats);
+}
+
+static void hinic3_get_drv_queue_stats(struct net_device *netdev, u64 *data)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct hinic3_txq_stats txq_stats = {};
+	struct hinic3_rxq_stats rxq_stats = {};
+	u16 i = 0, j, qid;
+	char *p;
+
+	for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) {
+		hinic3_txq_get_stats(&nic_dev->txqs[qid], &txq_stats);
+		for (j = 0; j < ARRAY_SIZE(hinic3_tx_queue_stats); j++, i++) {
+			p = (char *)&txq_stats +
+			    hinic3_tx_queue_stats[j].offset;
+			data[i] = *(u64 *)p;
+		}
+	}
+
+	i = nic_dev->q_params.num_qps * ARRAY_SIZE(hinic3_tx_queue_stats);
+	for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) {
+		hinic3_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats);
+		for (j = 0; j < ARRAY_SIZE(hinic3_rx_queue_stats); j++, i++) {
+			p = (char *)&rxq_stats +
+			    hinic3_rx_queue_stats[j].offset;
+			data[i] = *(u64 *)p;
+		}
+	}
+}
+
+static void hinic3_get_ethtool_stats(struct net_device *netdev,
+				     struct ethtool_stats *stats, u64 *data)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct l2nic_vport_stats vport_stats = {};
+	u16 i = 0, j;
+	char *p;
+	int err;
+
+	err = hinic3_get_vport_stats(nic_dev->hwdev,
+				     hinic3_global_func_id(nic_dev->hwdev),
+				     &vport_stats);
+	if (err)
+		netdev_err_once(netdev,
+				"Failed to get function stats from fw\n");
+
+	for (j = 0; j < ARRAY_SIZE(hinic3_function_stats); j++, i++) {
+		p = (char *)&vport_stats + hinic3_function_stats[j].offset;
+		data[i] = le64_to_cpu(*(__le64 *)p);
+	}
+
+	if (!HINIC3_IS_VF(nic_dev->hwdev))
+		i += hinic3_get_ethtool_port_stats(netdev, data + i);
+
+	hinic3_get_drv_queue_stats(netdev, data + i);
+}
+
+static void hinic3_get_eth_phy_stats(struct net_device *netdev,
+				     struct ethtool_eth_phy_stats *phy_stats)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct mag_cmd_port_stats *ps;
+	int err;
+
+	if (HINIC3_IS_VF(nic_dev->hwdev))
+		return;
+
+	ps = kmalloc_obj(*ps);
+	if (!ps)
+		return;
+
+	err = hinic3_get_phy_port_stats(nic_dev->hwdev, ps);
+	if (err) {
+		kfree(ps);
+		netdev_err_once(netdev,
+				"Failed to get eth phy stats from fw\n");
+		return;
+	}
+
+	phy_stats->SymbolErrorDuringCarrier =
+		le64_to_cpu(ps->mac_rx_sym_err_pkts);
+
+	kfree(ps);
+}
+
+static void hinic3_get_eth_mac_stats(struct net_device *netdev,
+				     struct ethtool_eth_mac_stats *mac_stats)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct mag_cmd_port_stats *ps;
+	int err;
+
+	if (HINIC3_IS_VF(nic_dev->hwdev))
+		return;
+
+	ps = kmalloc_obj(*ps);
+	if (!ps)
+		return;
+
+	err = hinic3_get_phy_port_stats(nic_dev->hwdev, ps);
+	if (err) {
+		kfree(ps);
+		netdev_err_once(netdev,
+				"Failed to get eth mac stats from fw\n");
+		return;
+	}
+
+	mac_stats->FramesTransmittedOK =
+		le64_to_cpu(ps->mac_tx_good_pkts);
+	mac_stats->FramesReceivedOK =
+		le64_to_cpu(ps->mac_rx_good_pkts);
+	mac_stats->FrameCheckSequenceErrors =
+		le64_to_cpu(ps->mac_rx_fcs_err_pkts);
+	mac_stats->OctetsTransmittedOK =
+		le64_to_cpu(ps->mac_tx_good_octs);
+	mac_stats->OctetsReceivedOK =
+		le64_to_cpu(ps->mac_rx_good_octs);
+	mac_stats->MulticastFramesXmittedOK =
+		le64_to_cpu(ps->mac_tx_multi_pkts);
+	mac_stats->BroadcastFramesXmittedOK =
+		le64_to_cpu(ps->mac_tx_broad_pkts);
+	mac_stats->MulticastFramesReceivedOK =
+		le64_to_cpu(ps->mac_rx_multi_pkts);
+	mac_stats->BroadcastFramesReceivedOK =
+		le64_to_cpu(ps->mac_rx_broad_pkts);
+
+	kfree(ps);
+}
+
+static void hinic3_get_eth_ctrl_stats(struct net_device *netdev,
+				      struct ethtool_eth_ctrl_stats *ctrl_stats)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct mag_cmd_port_stats *ps;
+	int err;
+
+	if (HINIC3_IS_VF(nic_dev->hwdev))
+		return;
+
+	ps = kmalloc_obj(*ps);
+	if (!ps)
+		return;
+
+	err = hinic3_get_phy_port_stats(nic_dev->hwdev, ps);
+	if (err) {
+		kfree(ps);
+		netdev_err_once(netdev,
+				"Failed to get eth ctrl stats from fw\n");
+		return;
+	}
+
+	ctrl_stats->MACControlFramesTransmitted =
+		le64_to_cpu(ps->mac_tx_control_pkts);
+	ctrl_stats->MACControlFramesReceived =
+		le64_to_cpu(ps->mac_rx_control_pkts);
+
+	kfree(ps);
+}
+
+static const struct ethtool_rmon_hist_range hinic3_rmon_ranges[] = {
+	{     0,    64 },
+	{    65,   127 },
+	{   128,   255 },
+	{   256,   511 },
+	{   512,  1023 },
+	{  1024,  1518 },
+	{  1519,  2047 },
+	{  2048,  4095 },
+	{  4096,  8191 },
+	{  8192,  9216 },
+	{  9217, 12287 },
+	{}
+};
+
+static void hinic3_get_rmon_stats(struct net_device *netdev,
+				  struct ethtool_rmon_stats *rmon_stats,
+				  const struct ethtool_rmon_hist_range **ranges)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct mag_cmd_port_stats *ps;
+	int err;
+
+	if (HINIC3_IS_VF(nic_dev->hwdev))
+		goto get_rmon_stats_err;
+
+	ps = kmalloc_obj(*ps);
+	if (!ps)
+		goto get_rmon_stats_err;
+
+	err = hinic3_get_phy_port_stats(nic_dev->hwdev, ps);
+	if (err) {
+		kfree(ps);
+		netdev_err_once(netdev,
+				"Failed to get eth rmon stats from fw\n");
+		goto get_rmon_stats_err;
+	}
+
+	rmon_stats->undersize_pkts = le64_to_cpu(ps->mac_rx_undersize_pkts);
+	rmon_stats->oversize_pkts  = le64_to_cpu(ps->mac_rx_oversize_pkts);
+	rmon_stats->fragments      = le64_to_cpu(ps->mac_rx_fragment_pkts);
+	rmon_stats->jabbers        = le64_to_cpu(ps->mac_rx_jabber_pkts);
+
+	rmon_stats->hist[0]  = le64_to_cpu(ps->mac_rx_64_oct_pkts);
+	rmon_stats->hist[1]  = le64_to_cpu(ps->mac_rx_65_127_oct_pkts);
+	rmon_stats->hist[2]  = le64_to_cpu(ps->mac_rx_128_255_oct_pkts);
+	rmon_stats->hist[3]  = le64_to_cpu(ps->mac_rx_256_511_oct_pkts);
+	rmon_stats->hist[4]  = le64_to_cpu(ps->mac_rx_512_1023_oct_pkts);
+	rmon_stats->hist[5]  = le64_to_cpu(ps->mac_rx_1024_1518_oct_pkts);
+	rmon_stats->hist[6]  = le64_to_cpu(ps->mac_rx_1519_2047_oct_pkts);
+	rmon_stats->hist[7]  = le64_to_cpu(ps->mac_rx_2048_4095_oct_pkts);
+	rmon_stats->hist[8]  = le64_to_cpu(ps->mac_rx_4096_8191_oct_pkts);
+	rmon_stats->hist[9]  = le64_to_cpu(ps->mac_rx_8192_9216_oct_pkts);
+	rmon_stats->hist[10] = le64_to_cpu(ps->mac_rx_9217_12287_oct_pkts);
+
+	rmon_stats->hist_tx[0]  = le64_to_cpu(ps->mac_tx_64_oct_pkts);
+	rmon_stats->hist_tx[1]  = le64_to_cpu(ps->mac_tx_65_127_oct_pkts);
+	rmon_stats->hist_tx[2]  = le64_to_cpu(ps->mac_tx_128_255_oct_pkts);
+	rmon_stats->hist_tx[3]  = le64_to_cpu(ps->mac_tx_256_511_oct_pkts);
+	rmon_stats->hist_tx[4]  = le64_to_cpu(ps->mac_tx_512_1023_oct_pkts);
+	rmon_stats->hist_tx[5]  = le64_to_cpu(ps->mac_tx_1024_1518_oct_pkts);
+	rmon_stats->hist_tx[6]  = le64_to_cpu(ps->mac_tx_1519_2047_oct_pkts);
+	rmon_stats->hist_tx[7]  = le64_to_cpu(ps->mac_tx_2048_4095_oct_pkts);
+	rmon_stats->hist_tx[8]  = le64_to_cpu(ps->mac_tx_4096_8191_oct_pkts);
+	rmon_stats->hist_tx[9]  = le64_to_cpu(ps->mac_tx_8192_9216_oct_pkts);
+	rmon_stats->hist_tx[10] = le64_to_cpu(ps->mac_tx_9217_12287_oct_pkts);
+
+	*ranges = hinic3_rmon_ranges;
+
+	kfree(ps);
+	return;
+
+get_rmon_stats_err:
+	*ranges = NULL;
+}
+
+static void hinic3_get_pause_stats(struct net_device *netdev,
+				   struct ethtool_pause_stats *pause_stats)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct mag_cmd_port_stats *ps;
+	int err;
+
+	if (HINIC3_IS_VF(nic_dev->hwdev))
+		return;
+
+	ps = kmalloc_obj(*ps);
+	if (!ps)
+		return;
+
+	err = hinic3_get_phy_port_stats(nic_dev->hwdev, ps);
+	if (err) {
+		kfree(ps);
+		netdev_err_once(netdev,
+				"Failed to get eth pause stats from fw\n");
+		return;
+	}
+
+	pause_stats->tx_pause_frames = le64_to_cpu(ps->mac_tx_pause_pkts);
+	pause_stats->rx_pause_frames = le64_to_cpu(ps->mac_rx_pause_pkts);
+
+	kfree(ps);
+}
+
+static void hinic3_get_pauseparam(struct net_device *netdev,
+				  struct ethtool_pauseparam *pause)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct hinic3_nic_pause_config nic_pause = {};
+	int err;
+
+	err = hinic3_get_pause_info(nic_dev, &nic_pause);
+	if (err) {
+		netdev_err_once(netdev, "Failed to get pauseparam\n");
+	} else {
+		pause->autoneg = AUTONEG_DISABLE;
+		pause->rx_pause = nic_pause.rx_pause;
+		pause->tx_pause = nic_pause.tx_pause;
+	}
+}
+
+static int hinic3_set_pauseparam(struct net_device *netdev,
+				 struct ethtool_pauseparam *pause)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct hinic3_nic_pause_config nic_pause = {};
+	int err;
+
+	if (HINIC3_IS_VF(nic_dev->hwdev))
+		return -EOPNOTSUPP;
+
+	if (pause->autoneg)
+		return -EOPNOTSUPP;
+
+	nic_pause.rx_pause = (u8)pause->rx_pause;
+	nic_pause.tx_pause = (u8)pause->tx_pause;
+
+	err = hinic3_set_pause_info(nic_dev, &nic_pause);
+	if (err)
+		netdev_err_once(netdev, "Failed to set pauseparam\n");
+	return err;
+}
+
 static const struct ethtool_ops hinic3_ethtool_ops = {
 	.supported_coalesce_params      = ETHTOOL_COALESCE_USECS |
 					  ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
@@ -417,6 +916,16 @@ static const struct ethtool_ops hinic3_ethtool_ops = {
 	.get_msglevel                   = hinic3_get_msglevel,
 	.set_msglevel                   = hinic3_set_msglevel,
 	.get_link                       = ethtool_op_get_link,
+	.get_strings                    = hinic3_get_strings,
+	.get_sset_count                 = hinic3_get_sset_count,
+	.get_ethtool_stats              = hinic3_get_ethtool_stats,
+	.get_eth_phy_stats              = hinic3_get_eth_phy_stats,
+	.get_eth_mac_stats              = hinic3_get_eth_mac_stats,
+	.get_eth_ctrl_stats             = hinic3_get_eth_ctrl_stats,
+	.get_rmon_stats                 = hinic3_get_rmon_stats,
+	.get_pause_stats                = hinic3_get_pause_stats,
+	.get_pauseparam                 = hinic3_get_pauseparam,
+	.set_pauseparam                 = hinic3_set_pauseparam,
 };
 
 void hinic3_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h
index cfc9daa3034fe..6b0f486ba590b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h
@@ -53,6 +53,17 @@ static inline void mgmt_msg_params_init_default(struct mgmt_msg_params *msg_para
 	msg_params->timeout_ms = 0;
 }
 
+static inline void
+mgmt_msg_params_init_in_out(struct mgmt_msg_params *msg_params, void *in_buf,
+			    void *out_buf, u32 in_buf_size, u32 out_buf_size)
+{
+	msg_params->buf_in = in_buf;
+	msg_params->buf_out = out_buf;
+	msg_params->in_size = in_buf_size;
+	msg_params->expected_out_size = out_buf_size;
+	msg_params->timeout_ms = 0;
+}
+
 enum cfg_cmd {
 	CFG_CMD_GET_DEV_CAP = 0,
 };
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h
index c5bca3c4af961..a2fe66a40b3ff 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h
@@ -143,6 +143,41 @@ struct l2nic_cmd_set_dcb_state {
 	u8                   rsvd[7];
 };
 
+struct l2nic_port_stats_info {
+	struct mgmt_msg_head msg_head;
+	u16                  func_id;
+	u16                  rsvd1;
+};
+
+struct l2nic_vport_stats {
+	__le64 tx_unicast_pkts_vport;
+	__le64 tx_unicast_bytes_vport;
+	__le64 tx_multicast_pkts_vport;
+	__le64 tx_multicast_bytes_vport;
+	__le64 tx_broadcast_pkts_vport;
+	__le64 tx_broadcast_bytes_vport;
+
+	__le64 rx_unicast_pkts_vport;
+	__le64 rx_unicast_bytes_vport;
+	__le64 rx_multicast_pkts_vport;
+	__le64 rx_multicast_bytes_vport;
+	__le64 rx_broadcast_pkts_vport;
+	__le64 rx_broadcast_bytes_vport;
+
+	__le64 tx_discard_vport;
+	__le64 rx_discard_vport;
+	__le64 tx_err_vport;
+	__le64 rx_err_vport;
+};
+
+struct l2nic_cmd_vport_stats {
+	struct mgmt_msg_head     msg_head;
+	u32                      stats_size;
+	u32                      rsvd1;
+	struct l2nic_vport_stats stats;
+	u64                      rsvd2[6];
+};
+
 struct l2nic_cmd_lro_config {
 	struct mgmt_msg_head msg_head;
 	u16                  func_id;
@@ -234,6 +269,7 @@ enum l2nic_cmd {
 	L2NIC_CMD_SET_VPORT_ENABLE    = 6,
 	L2NIC_CMD_SET_RX_MODE         = 7,
 	L2NIC_CMD_SET_SQ_CI_ATTR      = 8,
+	L2NIC_CMD_GET_VPORT_STAT      = 9,
 	L2NIC_CMD_CLEAR_QP_RESOURCE   = 11,
 	L2NIC_CMD_CFG_RX_LRO          = 13,
 	L2NIC_CMD_CFG_LRO_TIMER       = 14,
@@ -272,6 +308,7 @@ enum mag_cmd {
 	MAG_CMD_SET_PORT_ENABLE = 6,
 	MAG_CMD_GET_LINK_STATUS = 7,
 
+	MAG_CMD_GET_PORT_STAT   = 151,
 	MAG_CMD_GET_PORT_INFO   = 153,
 };
 
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
index da73811641a9d..10364c4dc11f9 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
@@ -5,6 +5,7 @@
 #include <linux/if_vlan.h>
 #include <linux/netdevice.h>
 #include <net/vxlan.h>
+#include <net/netdev_queues.h>
 
 #include "hinic3_hwif.h"
 #include "hinic3_nic_cfg.h"
@@ -802,14 +803,14 @@ static void hinic3_get_stats64(struct net_device *netdev,
 		txq_stats = &txq->txq_stats;
 		do {
 			start = u64_stats_fetch_begin(&txq_stats->syncp);
-			bytes += txq_stats->bytes;
-			packets += txq_stats->packets;
-			dropped += txq_stats->dropped;
+			bytes = txq_stats->bytes;
+			packets = txq_stats->packets;
+			dropped = txq_stats->dropped;
 		} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+		stats->tx_packets += packets;
+		stats->tx_bytes   += bytes;
+		stats->tx_dropped += dropped;
 	}
-	stats->tx_packets = packets;
-	stats->tx_bytes   = bytes;
-	stats->tx_dropped = dropped;
 
 	bytes = 0;
 	packets = 0;
@@ -823,17 +824,16 @@ static void hinic3_get_stats64(struct net_device *netdev,
 		rxq_stats = &rxq->rxq_stats;
 		do {
 			start = u64_stats_fetch_begin(&rxq_stats->syncp);
-			bytes += rxq_stats->bytes;
-			packets += rxq_stats->packets;
-			errors += rxq_stats->csum_errors +
-				rxq_stats->other_errors;
-			dropped += rxq_stats->dropped;
+			bytes = rxq_stats->bytes;
+			packets = rxq_stats->packets;
+			errors = rxq_stats->other_errors;
+			dropped = rxq_stats->dropped;
 		} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+		stats->rx_packets += packets;
+		stats->rx_bytes   += bytes;
+		stats->rx_errors  += errors;
+		stats->rx_dropped += dropped;
 	}
-	stats->rx_packets = packets;
-	stats->rx_bytes   = bytes;
-	stats->rx_errors  = errors;
-	stats->rx_dropped = dropped;
 }
 
 static void hinic3_nic_set_rx_mode(struct net_device *netdev)
@@ -867,7 +867,80 @@ static const struct net_device_ops hinic3_netdev_ops = {
 	.ndo_start_xmit       = hinic3_xmit_frame,
 };
 
+static void hinic3_get_queue_stats_rx(struct net_device *netdev, int i,
+				      struct netdev_queue_stats_rx *stats_rx)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct hinic3_rxq_stats *rxq_stats;
+	struct hinic3_rxq *rxq;
+	unsigned int start;
+
+	rxq = &nic_dev->rxqs[i];
+	rxq_stats = &rxq->rxq_stats;
+	do {
+		start = u64_stats_fetch_begin(&rxq_stats->syncp);
+		stats_rx->bytes = rxq_stats->bytes;
+		stats_rx->packets = rxq_stats->packets;
+		stats_rx->csum_bad = rxq_stats->csum_errors;
+		stats_rx->alloc_fail = rxq_stats->alloc_fail;
+	} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+}
+
+static void hinic3_get_queue_stats_tx(struct net_device *netdev, int i,
+				      struct netdev_queue_stats_tx *stats_tx)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	struct hinic3_txq_stats *txq_stats;
+	struct hinic3_txq *txq;
+	unsigned int start;
+
+	txq = &nic_dev->txqs[i];
+	txq_stats = &txq->txq_stats;
+	do {
+		start = u64_stats_fetch_begin(&txq_stats->syncp);
+		stats_tx->bytes = txq_stats->bytes;
+		stats_tx->packets = txq_stats->packets;
+		stats_tx->stop = txq_stats->busy;
+	} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+}
+
+static void hinic3_get_base_stats(struct net_device *netdev,
+				  struct netdev_queue_stats_rx *stats_rx,
+				  struct netdev_queue_stats_tx *stats_tx)
+{
+	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+	int i;
+
+	memset(stats_rx, 0, sizeof(*stats_rx));
+	memset(stats_tx, 0, sizeof(*stats_tx));
+
+	for (i = nic_dev->q_params.num_qps; i < nic_dev->max_qps; i++) {
+		struct netdev_queue_stats_rx rx = {0};
+
+		hinic3_get_queue_stats_rx(netdev, i, &rx);
+		stats_rx->bytes += rx.bytes;
+		stats_rx->packets += rx.packets;
+		stats_rx->csum_bad += rx.csum_bad;
+	}
+
+	for (i = nic_dev->q_params.num_qps; i < nic_dev->max_qps; i++) {
+		struct netdev_queue_stats_tx tx = {0};
+
+		hinic3_get_queue_stats_tx(netdev, i, &tx);
+		stats_tx->bytes += tx.bytes;
+		stats_tx->packets += tx.packets;
+		stats_tx->stop += tx.stop;
+	}
+}
+
+static const struct netdev_stat_ops hinic3_stat_ops = {
+	.get_queue_stats_rx  = hinic3_get_queue_stats_rx,
+	.get_queue_stats_tx  = hinic3_get_queue_stats_tx,
+	.get_base_stats      = hinic3_get_base_stats,
+};
+
 void hinic3_set_netdev_ops(struct net_device *netdev)
 {
 	netdev->netdev_ops = &hinic3_netdev_ops;
+	netdev->stat_ops = &hinic3_stat_ops;
 }
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
index de5a7984d2cb9..b5c696fe6cdfa 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
@@ -738,3 +738,74 @@ int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev,
 	return hinic3_cfg_hw_pause(nic_dev->hwdev, MGMT_MSG_CMD_OP_GET,
 				   nic_pause);
 }
+
+int hinic3_set_pause_info(struct hinic3_nic_dev *nic_dev,
+			  struct hinic3_nic_pause_config *nic_pause)
+{
+	return hinic3_cfg_hw_pause(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET,
+				   nic_pause);
+}
+
+int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id,
+			   struct l2nic_vport_stats *stats)
+{
+	struct l2nic_cmd_vport_stats vport_stats = {};
+	struct l2nic_port_stats_info stats_info = {};
+	struct mgmt_msg_params msg_params = {};
+	int err;
+
+	stats_info.func_id = func_id;
+
+	mgmt_msg_params_init_in_out(&msg_params, &stats_info, &vport_stats,
+				    sizeof(stats_info), sizeof(vport_stats));
+
+	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
+				       L2NIC_CMD_GET_VPORT_STAT, &msg_params);
+
+	if (err || vport_stats.msg_head.status) {
+		dev_err_once(hwdev->dev,
+			     "Failed to get function statistics, err: %d, status: 0x%x\n",
+			     err, vport_stats.msg_head.status);
+		return -EFAULT;
+	}
+
+	memcpy(stats, &vport_stats.stats, sizeof(*stats));
+
+	return 0;
+}
+
+int hinic3_get_phy_port_stats(struct hinic3_hwdev *hwdev,
+			      struct mag_cmd_port_stats *stats)
+{
+	struct mag_cmd_get_port_stats_in ps_in = {};
+	struct mag_cmd_get_port_stats_out *ps_out;
+	struct mgmt_msg_params msg_params = {};
+	int err;
+
+	ps_out = kzalloc_obj(*ps_out);
+	if (!ps_out)
+		return -ENOMEM;
+
+	ps_in.port_id = hinic3_physical_port_id(hwdev);
+
+	mgmt_msg_params_init_in_out(&msg_params, &ps_in, ps_out,
+				    sizeof(ps_in), sizeof(*ps_out));
+
+	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK,
+				       MAG_CMD_GET_PORT_STAT, &msg_params);
+
+	if (err || ps_out->head.status) {
+		dev_err_once(hwdev->dev,
+			     "Failed to get port statistics, err: %d, status: 0x%x\n",
+			     err, ps_out->head.status);
+		err = -EFAULT;
+		goto out;
+	}
+
+	memcpy(stats, &ps_out->counter, sizeof(*stats));
+
+out:
+	kfree(ps_out);
+
+	return err;
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
index 5d52202a8d4eb..beb491d667380 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
@@ -129,6 +129,110 @@ struct mag_cmd_get_xsfp_present {
 	u8                   rsvd[2];
 };
 
+struct mag_cmd_port_stats {
+	__le64 mac_tx_fragment_pkts;
+	__le64 mac_tx_undersize_pkts;
+	__le64 mac_tx_undermin_pkts;
+	__le64 mac_tx_64_oct_pkts;
+	__le64 mac_tx_65_127_oct_pkts;
+	__le64 mac_tx_128_255_oct_pkts;
+	__le64 mac_tx_256_511_oct_pkts;
+	__le64 mac_tx_512_1023_oct_pkts;
+	__le64 mac_tx_1024_1518_oct_pkts;
+	__le64 mac_tx_1519_2047_oct_pkts;
+	__le64 mac_tx_2048_4095_oct_pkts;
+	__le64 mac_tx_4096_8191_oct_pkts;
+	__le64 mac_tx_8192_9216_oct_pkts;
+	__le64 mac_tx_9217_12287_oct_pkts;
+	__le64 mac_tx_12288_16383_oct_pkts;
+	__le64 mac_tx_jumbo_bad_pkts;
+	__le64 mac_tx_jumbo_good_pkts;
+	__le64 mac_tx_oversize_pkts;
+	__le64 mac_tx_jabber_pkts;
+	__le64 mac_tx_bad_pkts;
+	__le64 mac_tx_bad_octs;
+	__le64 mac_tx_good_pkts;
+	__le64 mac_tx_good_octs;
+	__le64 mac_tx_total_pkts;
+	__le64 mac_tx_total_octs;
+	__le64 mac_tx_uni_pkts;
+	__le64 mac_tx_multi_pkts;
+	__le64 mac_tx_broad_pkts;
+	__le64 mac_tx_pause_pkts;
+	__le64 mac_tx_pfc_pkts;
+	__le64 mac_tx_pfc_pri0_pkts;
+	__le64 mac_tx_pfc_pri1_pkts;
+	__le64 mac_tx_pfc_pri2_pkts;
+	__le64 mac_tx_pfc_pri3_pkts;
+	__le64 mac_tx_pfc_pri4_pkts;
+	__le64 mac_tx_pfc_pri5_pkts;
+	__le64 mac_tx_pfc_pri6_pkts;
+	__le64 mac_tx_pfc_pri7_pkts;
+	__le64 mac_tx_control_pkts;
+	__le64 mac_tx_err_all_pkts;
+	__le64 mac_tx_from_app_good_pkts;
+	__le64 mac_tx_from_app_bad_pkts;
+
+	__le64 mac_rx_fragment_pkts;
+	__le64 mac_rx_undersize_pkts;
+	__le64 mac_rx_undermin_pkts;
+	__le64 mac_rx_64_oct_pkts;
+	__le64 mac_rx_65_127_oct_pkts;
+	__le64 mac_rx_128_255_oct_pkts;
+	__le64 mac_rx_256_511_oct_pkts;
+	__le64 mac_rx_512_1023_oct_pkts;
+	__le64 mac_rx_1024_1518_oct_pkts;
+	__le64 mac_rx_1519_2047_oct_pkts;
+	__le64 mac_rx_2048_4095_oct_pkts;
+	__le64 mac_rx_4096_8191_oct_pkts;
+	__le64 mac_rx_8192_9216_oct_pkts;
+	__le64 mac_rx_9217_12287_oct_pkts;
+	__le64 mac_rx_12288_16383_oct_pkts;
+	__le64 mac_rx_jumbo_bad_pkts;
+	__le64 mac_rx_jumbo_good_pkts;
+	__le64 mac_rx_oversize_pkts;
+	__le64 mac_rx_jabber_pkts;
+	__le64 mac_rx_bad_pkts;
+	__le64 mac_rx_bad_octs;
+	__le64 mac_rx_good_pkts;
+	__le64 mac_rx_good_octs;
+	__le64 mac_rx_total_pkts;
+	__le64 mac_rx_total_octs;
+	__le64 mac_rx_uni_pkts;
+	__le64 mac_rx_multi_pkts;
+	__le64 mac_rx_broad_pkts;
+	__le64 mac_rx_pause_pkts;
+	__le64 mac_rx_pfc_pkts;
+	__le64 mac_rx_pfc_pri0_pkts;
+	__le64 mac_rx_pfc_pri1_pkts;
+	__le64 mac_rx_pfc_pri2_pkts;
+	__le64 mac_rx_pfc_pri3_pkts;
+	__le64 mac_rx_pfc_pri4_pkts;
+	__le64 mac_rx_pfc_pri5_pkts;
+	__le64 mac_rx_pfc_pri6_pkts;
+	__le64 mac_rx_pfc_pri7_pkts;
+	__le64 mac_rx_control_pkts;
+	__le64 mac_rx_sym_err_pkts;
+	__le64 mac_rx_fcs_err_pkts;
+	__le64 mac_rx_send_app_good_pkts;
+	__le64 mac_rx_send_app_bad_pkts;
+	__le64 mac_rx_unfilter_pkts;
+};
+
+struct mag_cmd_get_port_stats_in {
+	struct mgmt_msg_head head;
+
+	u8                   port_id;
+	u8                   rsvd0[3];
+};
+
+struct mag_cmd_get_port_stats_out {
+	struct mgmt_msg_head      head;
+
+	struct mag_cmd_port_stats counter;
+	u64                       rsvd1[15];
+};
+
 enum link_err_type {
 	LINK_ERR_MODULE_UNRECOGENIZED,
 	LINK_ERR_NUM,
@@ -214,5 +318,11 @@ int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id);
 
 int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev,
 			  struct hinic3_nic_pause_config *nic_pause);
+int hinic3_set_pause_info(struct hinic3_nic_dev *nic_dev,
+			  struct hinic3_nic_pause_config *nic_pause);
 
+int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id,
+			   struct l2nic_vport_stats *stats);
+int hinic3_get_phy_port_stats(struct hinic3_hwdev *hwdev,
+			      struct mag_cmd_port_stats *stats);
 #endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
index 309ab59013797..ae4ccff4a09a9 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
@@ -43,10 +43,7 @@ static void hinic3_rxq_clean_stats(struct hinic3_rxq_stats *rxq_stats)
 	rxq_stats->other_errors = 0;
 	rxq_stats->dropped = 0;
 	rxq_stats->rx_buf_empty = 0;
-
-	rxq_stats->alloc_skb_err = 0;
-	rxq_stats->alloc_rx_buf_err = 0;
-	rxq_stats->restore_drop_sge = 0;
+	rxq_stats->alloc_fail = 0;
 	u64_stats_update_end(&rxq_stats->syncp);
 }
 
@@ -147,6 +144,8 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
 {
 	u32 i, free_wqebbs = rxq->delta - 1;
 	struct hinic3_rx_info *rx_info;
+	struct u64_stats_sync *syncp;
+	unsigned long flags;
 	dma_addr_t dma_addr;
 	int err;
 
@@ -155,8 +154,13 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
 
 		err = rx_alloc_mapped_page(rxq->page_pool, rx_info,
 					   rxq->buf_len);
-		if (unlikely(err))
+		if (unlikely(err)) {
+			syncp = &rxq->rxq_stats.syncp;
+			flags = u64_stats_update_begin_irqsave(syncp);
+			rxq->rxq_stats.alloc_fail++;
+			u64_stats_update_end_irqrestore(syncp, flags);
 			break;
+		}
 
 		dma_addr = page_pool_get_dma_addr(rx_info->page) +
 			rx_info->page_offset;
@@ -170,6 +174,11 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
 				rxq->next_to_update << HINIC3_NORMAL_RQ_WQE);
 		rxq->delta -= i;
 		rxq->next_to_alloc = rxq->next_to_update;
+	} else if (free_wqebbs == rxq->q_depth - 1) {
+		syncp = &rxq->rxq_stats.syncp;
+		flags = u64_stats_update_begin_irqsave(syncp);
+		rxq->rxq_stats.rx_buf_empty++;
+		u64_stats_update_end_irqrestore(syncp, flags);
 	}
 
 	return i;
@@ -330,10 +339,23 @@ static void hinic3_rx_csum(struct hinic3_rxq *rxq, u32 offload_type,
 	struct net_device *netdev = rxq->netdev;
 	bool l2_tunnel;
 
+	/* HW ensures that only 1 bit is set in csum_err. */
+	if (unlikely(csum_err == HINIC3_RX_CSUM_IPSU_OTHER_ERR)) {
+		u64_stats_update_begin(&rxq->rxq_stats.syncp);
+		rxq->rxq_stats.other_errors++;
+		u64_stats_update_end(&rxq->rxq_stats.syncp);
+	}
+
 	if (!(netdev->features & NETIF_F_RXCSUM))
 		return;
 
 	if (unlikely(csum_err)) {
+		if (csum_err != HINIC3_RX_CSUM_HW_CHECK_NONE &&
+		    csum_err != HINIC3_RX_CSUM_IPSU_OTHER_ERR) {
+			u64_stats_update_begin(&rxq->rxq_stats.syncp);
+			rxq->rxq_stats.csum_errors++;
+			u64_stats_update_end(&rxq->rxq_stats.syncp);
+		}
 		/* pkt type is recognized by HW, and csum is wrong */
 		skb->ip_summed = CHECKSUM_NONE;
 		return;
@@ -387,8 +409,12 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_rq_cqe *rx_cqe,
 	u16 num_lro;
 
 	skb = hinic3_fetch_rx_buffer(rxq, pkt_len);
-	if (unlikely(!skb))
+	if (unlikely(!skb)) {
+		u64_stats_update_begin(&rxq->rxq_stats.syncp);
+		rxq->rxq_stats.alloc_fail++;
+		u64_stats_update_end(&rxq->rxq_stats.syncp);
 		return -ENOMEM;
+	}
 
 	/* place header in linear portion of buffer */
 	if (skb_is_nonlinear(skb))
@@ -555,6 +581,7 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)
 	struct hinic3_nic_dev *nic_dev = netdev_priv(rxq->netdev);
 	u32 sw_ci, status, pkt_len, vlan_len;
 	struct hinic3_rq_cqe *rx_cqe;
+	u64 rx_bytes = 0;
 	u32 num_wqe = 0;
 	int nr_pkts = 0;
 	u16 num_lro;
@@ -575,6 +602,7 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)
 			break;
 
 		nr_pkts++;
+		rx_bytes += pkt_len;
 		num_lro = RQ_CQE_STATUS_GET(status, NUM_LRO);
 		if (num_lro)
 			num_wqe += hinic3_get_sge_num(rxq, pkt_len);
@@ -588,5 +616,24 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)
 	if (rxq->delta >= HINIC3_RX_BUFFER_WRITE)
 		hinic3_rx_fill_buffers(rxq);
 
+	u64_stats_update_begin(&rxq->rxq_stats.syncp);
+	rxq->rxq_stats.packets += (u64)nr_pkts;
+	rxq->rxq_stats.bytes += rx_bytes;
+	u64_stats_update_end(&rxq->rxq_stats.syncp);
 	return nr_pkts;
 }
+
+void hinic3_rxq_get_stats(struct hinic3_rxq *rxq,
+			  struct hinic3_rxq_stats *stats)
+{
+	struct hinic3_rxq_stats *rxq_stats = &rxq->rxq_stats;
+	unsigned int start;
+
+	do {
+		start = u64_stats_fetch_begin(&rxq_stats->syncp);
+		stats->csum_errors = rxq_stats->csum_errors;
+		stats->other_errors = rxq_stats->other_errors;
+		stats->rx_buf_empty = rxq_stats->rx_buf_empty;
+		stats->alloc_fail = rxq_stats->alloc_fail;
+	} while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
index 06d1b3299e7cf..a54184beedc9f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
@@ -8,6 +8,10 @@
 #include <linux/dim.h>
 #include <linux/netdevice.h>
 
+/* rx cqe checksum err */
+#define HINIC3_RX_CSUM_HW_CHECK_NONE    BIT(7)
+#define HINIC3_RX_CSUM_IPSU_OTHER_ERR   BIT(8)
+
 #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK           GENMASK(4, 0)
 #define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK            GENMASK(6, 5)
 #define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK  GENMASK(11, 8)
@@ -37,9 +41,7 @@ struct hinic3_rxq_stats {
 	u64                   other_errors;
 	u64                   dropped;
 	u64                   rx_buf_empty;
-	u64                   alloc_skb_err;
-	u64                   alloc_rx_buf_err;
-	u64                   restore_drop_sge;
+	u64                   alloc_fail;
 	struct u64_stats_sync syncp;
 };
 
@@ -125,4 +127,6 @@ int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq,
 			  u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res);
 int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget);
 
+void hinic3_rxq_get_stats(struct hinic3_rxq *rxq,
+			  struct hinic3_rxq_stats *stats);
 #endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
index f92568f0f00b7..b0a0ffb1052b3 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
@@ -25,11 +25,9 @@ static void hinic3_txq_clean_stats(struct hinic3_txq_stats *txq_stats)
 	txq_stats->dropped = 0;
 
 	txq_stats->skb_pad_err = 0;
-	txq_stats->frag_len_overflow = 0;
 	txq_stats->offload_cow_skb_err = 0;
 	txq_stats->map_frag_err = 0;
 	txq_stats->unknown_tunnel_pkt = 0;
-	txq_stats->frag_size_err = 0;
 	u64_stats_update_end(&txq_stats->syncp);
 }
 
@@ -97,8 +95,12 @@ static int hinic3_tx_map_skb(struct net_device *netdev, struct sk_buff *skb,
 
 	dma_info[0].dma = dma_map_single(&pdev->dev, skb->data,
 					 skb_headlen(skb), DMA_TO_DEVICE);
-	if (dma_mapping_error(&pdev->dev, dma_info[0].dma))
+	if (dma_mapping_error(&pdev->dev, dma_info[0].dma)) {
+		u64_stats_update_begin(&txq->txq_stats.syncp);
+		txq->txq_stats.map_frag_err++;
+		u64_stats_update_end(&txq->txq_stats.syncp);
 		return -EFAULT;
+	}
 
 	dma_info[0].len = skb_headlen(skb);
 
@@ -117,6 +119,9 @@ static int hinic3_tx_map_skb(struct net_device *netdev, struct sk_buff *skb,
 						     skb_frag_size(frag),
 						     DMA_TO_DEVICE);
 		if (dma_mapping_error(&pdev->dev, dma_info[idx].dma)) {
+			u64_stats_update_begin(&txq->txq_stats.syncp);
+			txq->txq_stats.map_frag_err++;
+			u64_stats_update_end(&txq->txq_stats.syncp);
 			err = -EFAULT;
 			goto err_unmap_page;
 		}
@@ -260,6 +265,9 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct hinic3_sq_task *task,
 		if (l4_proto != IPPROTO_UDP ||
 		    ((struct udphdr *)skb_transport_header(skb))->dest !=
 		    VXLAN_OFFLOAD_PORT_LE) {
+			u64_stats_update_begin(&txq->txq_stats.syncp);
+			txq->txq_stats.unknown_tunnel_pkt++;
+			u64_stats_update_end(&txq->txq_stats.syncp);
 			/* Unsupported tunnel packet, disable csum offload */
 			return skb_checksum_help(skb);
 		}
@@ -541,8 +549,12 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
 	u32 offload;
 	int err;
 
-	if (skb_put_padto(skb, MIN_SKB_LEN))
+	if (skb_put_padto(skb, MIN_SKB_LEN)) {
+		u64_stats_update_begin(&txq->txq_stats.syncp);
+		txq->txq_stats.skb_pad_err++;
+		u64_stats_update_end(&txq->txq_stats.syncp);
 		goto err_out;
+	}
 
 	offload = hinic3_tx_offload(skb, &task, &queue_info, txq);
 	num_sge = skb_shinfo(skb)->nr_frags + 1;
@@ -557,10 +569,16 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
 					hinic3_wq_free_wqebbs(&txq->sq->wq),
 					txq->tx_start_thrs);
 
+		u64_stats_update_begin(&txq->txq_stats.syncp);
+		txq->txq_stats.busy++;
+		u64_stats_update_end(&txq->txq_stats.syncp);
 		return NETDEV_TX_BUSY;
 	}
 
 	if (unlikely(offload == HINIC3_TX_OFFLOAD_INVALID)) {
+		u64_stats_update_begin(&txq->txq_stats.syncp);
+		txq->txq_stats.offload_cow_skb_err++;
+		u64_stats_update_end(&txq->txq_stats.syncp);
 		goto err_drop_pkt;
 	} else if (!offload) {
 		wqebb_cnt -= 1;
@@ -599,11 +617,19 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
 	hinic3_write_db(txq->sq, 0, DB_CFLAG_DP_SQ,
 			hinic3_get_sq_local_pi(txq->sq));
 
+	u64_stats_update_begin(&txq->txq_stats.syncp);
+	txq->txq_stats.bytes += skb->len;
+	txq->txq_stats.packets += 1;
+	u64_stats_update_end(&txq->txq_stats.syncp);
+
 	return NETDEV_TX_OK;
 
 err_drop_pkt:
 	dev_kfree_skb_any(skb);
 err_out:
+	u64_stats_update_begin(&txq->txq_stats.syncp);
+	txq->txq_stats.dropped++;
+	u64_stats_update_end(&txq->txq_stats.syncp);
 	return NETDEV_TX_OK;
 }
 
@@ -611,18 +637,25 @@ netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
 	u16 q_id = skb_get_queue_mapping(skb);
-
-	if (unlikely(!netif_carrier_ok(netdev)))
-		goto err_drop_pkt;
+	struct hinic3_txq *txq;
 
 	if (unlikely(q_id >= nic_dev->q_params.num_qps))
+		goto err_qid_out;
+
+	txq = &nic_dev->txqs[q_id];
+
+	if (unlikely(!netif_carrier_ok(netdev)))
 		goto err_drop_pkt;
 
-	return hinic3_send_one_skb(skb, netdev, &nic_dev->txqs[q_id]);
+	return hinic3_send_one_skb(skb, netdev, txq);
 
 err_drop_pkt:
-	dev_kfree_skb_any(skb);
+	u64_stats_update_begin(&txq->txq_stats.syncp);
+	txq->txq_stats.dropped++;
+	u64_stats_update_end(&txq->txq_stats.syncp);
 
+err_qid_out:
+	dev_kfree_skb_any(skb);
 	return NETDEV_TX_OK;
 }
 
@@ -795,3 +828,19 @@ bool hinic3_tx_poll(struct hinic3_txq *txq, int budget)
 
 	return pkts == HINIC3_TX_POLL_WEIGHT;
 }
+
+void hinic3_txq_get_stats(struct hinic3_txq *txq,
+			  struct hinic3_txq_stats *stats)
+{
+	struct hinic3_txq_stats *txq_stats = &txq->txq_stats;
+	unsigned int start;
+
+	do {
+		start = u64_stats_fetch_begin(&txq_stats->syncp);
+		stats->busy = txq_stats->busy;
+		stats->skb_pad_err = txq_stats->skb_pad_err;
+		stats->offload_cow_skb_err = txq_stats->offload_cow_skb_err;
+		stats->map_frag_err = txq_stats->map_frag_err;
+		stats->unknown_tunnel_pkt = txq_stats->unknown_tunnel_pkt;
+	} while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h
index 00194f2a1bcc1..9e429362b9363 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h
@@ -106,11 +106,9 @@ struct hinic3_txq_stats {
 	u64                   busy;
 	u64                   dropped;
 	u64                   skb_pad_err;
-	u64                   frag_len_overflow;
 	u64                   offload_cow_skb_err;
 	u64                   map_frag_err;
 	u64                   unknown_tunnel_pkt;
-	u64                   frag_size_err;
 	struct u64_stats_sync syncp;
 };
 
@@ -160,4 +158,6 @@ netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 bool hinic3_tx_poll(struct hinic3_txq *txq, int budget);
 void hinic3_flush_txqs(struct net_device *netdev);
 
+void hinic3_txq_get_stats(struct hinic3_txq *txq,
+			  struct hinic3_txq_stats *stats);
 #endif

3/2 2026/10/22 23:07 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 22747
							output: 34
							thoughts: 394
						

Thoughts:
**Patch Analysis for Syzkaller Fuzzing**

Okay, let's dive into this patch and assess its fuzzing potential with syzkaller. My initial step is always to examine the diff closely. First, I see the affected files are all within `drivers/net/ethernet/huawei/hinic3/`. Alright, so we're looking at code related to Huawei's network interface cards, specifically the `hinic3` driver.

Now, my radar is up. I need to understand what `hinic3` is. Memory says it's a Huawei Intelligent Network Interface Card. Is this a PCI network device driver? That's key. To quickly confirm, let's use grepper and see what's in the `Kconfig` and `Makefile` files within that directory. This should give me the crucial context I need to determine if it's a target for syzkaller. Network drivers are often good candidates, depending on how they interface with the kernel. Time to dig in a bit more.



4/2 2026/10/22 23:07 tool grepper
0m Args:
{
  "Expression": "hinic3",
  "PathPrefixes": [
    "drivers/net/ethernet/huawei/"
  ]
}

Results:
{
  "Output": "\nFull output is too long, showing 200 out of 6846 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (46 files in total):\ndrivers/net/ethernet/huawei/Kconfig:1\ndrivers/net/ethernet/huawei/Makefile:1\ndrivers/net/ethernet/huawei/hinic3/Kconfig:1\ndrivers/net/ethernet/huawei/hinic3/Makefile:23\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:130\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.h:41\ndrivers/net/ethernet/huawei/hinic3/hinic3_common.c:8\ndrivers/net/ethernet/huawei/hinic3/hinic3_common.h:11\ndrivers/net/ethernet/huawei/hinic3/hinic3_eqs.c:123\ndrivers/net/ethernet/huawei/hinic3/hinic3_eqs.h:38\ndrivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c:173\ndrivers/net/ethernet/huawei/hinic3/hinic3_filter.c:85\ndrivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c:52\ndrivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h:18\ndrivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c:81\ndrivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h:21\ndrivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h:1\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c:130\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h:28\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwif.c:88\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwif.h:34\ndrivers/net/ethernet/huawei/hinic3/hinic3_irq.c:57\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:95\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.h:8\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c:131\ndrivers/net/ethernet/huawei/hinic3/hinic3_mbox.c:94\ndrivers/net/ethernet/huawei/hinic3/hinic3_mbox.h:18\ndrivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c:35\ndrivers/net/ethernet/huawei/hinic3/hinic3_mgmt.h:13\ndrivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h:2\ndrivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c:202\ndrivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c:106\ndrivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h:46\ndrivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h:36\ndrivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c:144\ndrivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h:34\ndrivers/net/ethernet/huawei/hinic3/hinic3_queue_common.c:11\ndrivers/net/ethernet/huawei/hinic3/hinic3_queue_common.h:11\ndrivers/net/ethernet/huawei/hinic3/hinic3_rss.c:64\ndrivers/net/ethernet/huawei/hinic3/hinic3_rss.h:4\ndrivers/net/ethernet/huawei/hinic3/hinic3_rx.c:70\ndrivers/net/ethernet/huawei/hinic3/hinic3_rx.h:23\ndrivers/net/ethernet/huawei/hinic3/hinic3_tx.c:119\ndrivers/net/ethernet/huawei/hinic3/hinic3_tx.h:32\ndrivers/net/ethernet/huawei/hinic3/hinic3_wq.c:20\ndrivers/net/ethernet/huawei/hinic3/hinic3_wq.h:17\n\ndrivers/net/ethernet/huawei/Kconfig=18=source \"drivers/net/ethernet/huawei/hinic/Kconfig\"\ndrivers/net/ethernet/huawei/Kconfig:19:source \"drivers/net/ethernet/huawei/hinic3/Kconfig\"\ndrivers/net/ethernet/huawei/Kconfig-20-\n--\ndrivers/net/ethernet/huawei/Makefile=6=obj-$(CONFIG_HINIC) += hinic/\ndrivers/net/ethernet/huawei/Makefile:7:obj-$(CONFIG_HINIC3) += hinic3/\n--\ndrivers/net/ethernet/huawei/hinic3/Kconfig=6=config HINIC3\n--\ndrivers/net/ethernet/huawei/hinic3/Kconfig-20-\t  To compile this driver as a module, choose M here.\ndrivers/net/ethernet/huawei/hinic3/Kconfig:21:\t  The module will be called hinic3.\n--\ndrivers/net/ethernet/huawei/hinic3/Makefile-3-\ndrivers/net/ethernet/huawei/hinic3/Makefile:4:obj-$(CONFIG_HINIC3) += hinic3.o\ndrivers/net/ethernet/huawei/hinic3/Makefile-5-\ndrivers/net/ethernet/huawei/hinic3/Makefile:6:hinic3-objs := hinic3_cmdq.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:7:\t       hinic3_common.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:8:\t       hinic3_eqs.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:9:\t       hinic3_ethtool.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:10:\t       hinic3_filter.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:11:\t       hinic3_hw_cfg.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:12:\t       hinic3_hw_comm.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:13:\t       hinic3_hwdev.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:14:\t       hinic3_hwif.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:15:\t       hinic3_irq.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:16:\t       hinic3_lld.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:17:\t       hinic3_main.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:18:\t       hinic3_mbox.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:19:\t       hinic3_mgmt.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:20:\t       hinic3_netdev_ops.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:21:\t       hinic3_nic_cfg.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:22:\t       hinic3_nic_io.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:23:\t       hinic3_queue_common.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:24:\t       hinic3_rss.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:25:\t       hinic3_rx.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:26:\t       hinic3_tx.o \\\ndrivers/net/ethernet/huawei/hinic3/Makefile:27:\t       hinic3_wq.o\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-7-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:8:#include \"hinic3_cmdq.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:9:#include \"hinic3_eqs.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:10:#include \"hinic3_hwdev.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:11:#include \"hinic3_hwif.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:12:#include \"hinic3_mbox.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-13-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c=112=enum cmdq_cmd_type {\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-118-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:119:static void hinic3_dump_cmdq_wqe_head(struct hinic3_hwdev *hwdev,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-120-\t\t\t\t      struct cmdq_wqe *wqe)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-132-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:133:static struct cmdq_wqe *cmdq_read_wqe(struct hinic3_wq *wq, u16 *ci)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-134-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:135:\tif (hinic3_wq_get_used(wq) == 0)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-136-\t\treturn NULL;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-142-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:143:struct hinic3_cmd_buf *hinic3_alloc_cmd_buf(struct hinic3_hwdev *hwdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-144-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:145:\tstruct hinic3_cmd_buf *cmd_buf;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:146:\tstruct hinic3_cmdqs *cmdqs;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-147-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-171-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:172:void hinic3_free_cmd_buf(struct hinic3_hwdev *hwdev,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:173:\t\t\t struct hinic3_cmd_buf *cmd_buf)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-174-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:175:\tstruct hinic3_cmdqs *cmdqs;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-176-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-185-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:186:static void cmdq_clear_cmd_buf(struct hinic3_cmdq_cmd_info *cmd_info,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:187:\t\t\t       struct hinic3_hwdev *hwdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-188-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-189-\tif (cmd_info-\u003ebuf_in) {\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:190:\t\thinic3_free_cmd_buf(hwdev, cmd_info-\u003ebuf_in);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-191-\t\tcmd_info-\u003ebuf_in = NULL;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-194-\tif (cmd_info-\u003ebuf_out) {\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:195:\t\thinic3_free_cmd_buf(hwdev, cmd_info-\u003ebuf_out);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-196-\t\tcmd_info-\u003ebuf_out = NULL;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-199-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:200:static void clear_wqe_complete_bit(struct hinic3_cmdq *cmdq,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-201-\t\t\t\t   struct cmdq_wqe *wqe, u16 ci)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-217-\twmb(); /* verify wqe is clear before updating ci */\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:218:\thinic3_wq_put_wqebbs(\u0026cmdq-\u003ewq, CMDQ_WQE_NUM_WQEBBS);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-219-}\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-220-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:221:static int cmdq_arm_ceq_handler(struct hinic3_cmdq *cmdq,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-222-\t\t\t\tstruct cmdq_wqe *wqe, u16 ci)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-234-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:235:static void cmdq_update_cmd_status(struct hinic3_cmdq *cmdq, u16 prod_idx,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-236-\t\t\t\t   struct cmdq_wqe *wqe)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-237-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:238:\tstruct hinic3_cmdq_cmd_info *cmd_info;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-239-\tstruct cmdq_wqe_lcmd *wqe_lcmd;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-252-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:253:static void cmdq_sync_cmd_handler(struct hinic3_cmdq *cmdq,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-254-\t\t\t\t  struct cmdq_wqe *wqe, u16 ci)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-274-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:275:void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev, __le32 ceqe_data)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-276-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:277:\tenum hinic3_cmdq_type cmdq_type = CMDQ_CEQE_GET(ceqe_data, TYPE);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:278:\tstruct hinic3_cmdqs *cmdqs = hwdev-\u003ecmdqs;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:279:\tstruct hinic3_cmdq_cmd_info *cmd_info;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-280-\tstruct cmdq_wqe_lcmd *wqe_lcmd;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:281:\tstruct hinic3_cmdq *cmdq;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-282-\tstruct cmdq_wqe *wqe;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-297-\t\t\t\t cmdq_type, ci);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:298:\t\t\thinic3_dump_cmdq_wqe_head(hwdev, wqe);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-299-\t\t\tfallthrough;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-334-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:335:static int cmdq_params_valid(const struct hinic3_hwdev *hwdev,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:336:\t\t\t     const struct hinic3_cmd_buf *buf_in)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-337-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-346-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:347:static int wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-348-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c=364=static void cmdq_set_completion(struct cmdq_completion *complete,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:365:\t\t\t\tstruct hinic3_cmd_buf *buf_out)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-366-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:367:\tstruct hinic3_sge *sge = \u0026complete-\u003eresp.sge;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-368-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:369:\thinic3_set_sge(sge, buf_out-\u003edma_addr, cpu_to_le32(CMDQ_BUF_SIZE));\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-370-}\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-371-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:372:static struct cmdq_wqe *cmdq_get_wqe(struct hinic3_wq *wq, u16 *pi)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-373-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:374:\tif (!hinic3_wq_free_wqebbs(wq))\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-375-\t\treturn NULL;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-376-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:377:\treturn hinic3_wq_get_one_wqebb(wq, pi);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-378-}\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c=380=static void cmdq_set_lcmd_bufdesc(struct cmdq_wqe_lcmd *wqe,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:381:\t\t\t\t  struct hinic3_cmd_buf *buf_in)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-382-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:383:\thinic3_set_sge(\u0026wqe-\u003ebuf_desc.sge, buf_in-\u003edma_addr,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-384-\t\t       (__force __le32)buf_in-\u003esize);\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-386-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:387:static void cmdq_set_db(struct hinic3_cmdq *cmdq,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:388:\t\t\tenum hinic3_cmdq_type cmdq_type, u16 prod_idx)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-389-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c=459=static void cmdq_set_lcmd_wqe(struct cmdq_wqe *wqe,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-460-\t\t\t      enum cmdq_cmd_type cmd_type,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:461:\t\t\t      struct hinic3_cmd_buf *buf_in,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:462:\t\t\t      struct hinic3_cmd_buf *buf_out,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-463-\t\t\t      u8 wrapped, u8 mod, u8 cmd, u16 prod_idx)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-484-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:485:static int hinic3_cmdq_sync_timeout_check(struct hinic3_cmdq *cmdq,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-486-\t\t\t\t\t  struct cmdq_wqe *wqe, u16 pi)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-503-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:504:static void clear_cmd_info(struct hinic3_cmdq_cmd_info *cmd_info,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:505:\t\t\t   const struct hinic3_cmdq_cmd_info *saved_cmd_info)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-506-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-516-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:517:static int wait_cmdq_sync_cmd_completion(struct hinic3_cmdq *cmdq,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:518:\t\t\t\t\t struct hinic3_cmdq_cmd_info *cmd_info,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:519:\t\t\t\t\t struct hinic3_cmdq_cmd_info *saved_cmd_info,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-520-\t\t\t\t\t u64 curr_msg_id, u16 curr_prod_idx,\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-540-\tif (curr_msg_id == cmd_info-\u003ecmdq_msg_id) {\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:541:\t\terr = hinic3_cmdq_sync_timeout_check(cmdq, curr_wqe,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-542-\t\t\t\t\t\t     curr_prod_idx);\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-555-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:556:\thinic3_dump_ceq_info(cmdq-\u003ehwdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-557-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-560-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:561:static int cmdq_sync_cmd_exec(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:562:\t\t\t      struct hinic3_cmd_buf *buf_in,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:563:\t\t\t      struct hinic3_cmd_buf *buf_out,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-564-\t\t\t      __le64 *out_param, u8 cmd_type, u8 wqe_cmd)\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-565-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:566:\tstruct hinic3_cmdq_cmd_info *cmd_info, saved_cmd_info;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-567-\tint cmpt_code = CMDQ_SEND_CMPT_CODE;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-568-\tstruct cmdq_wqe *curr_wqe, wqe = {};\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:569:\tstruct hinic3_wq *wq = \u0026cmdq-\u003ewq;\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-570-\tu16 curr_prod_idx, next_prod_idx;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c-634-\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:635:static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,\ndrivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c:636:\t\t\t\t     struct hinic3_cmd_buf *buf_in,\n\n"
}

5/2 2026/10/22 23:07 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 31146
							output: 42
							thoughts: 22
						

Thoughts:
Here's a first-person summary, tailored for an expert audience, of the provided text:

**Diving into the hinic3 Kconfig**

Okay, so I need to understand the configuration options for the Huawei hinic3 Ethernet driver. My immediate thought is, "Let's crack open the `drivers/net/ethernet/huawei/hinic3/Kconfig` file." I expect it to contain all the conditional build options, dependencies, and help text that determine how the hinic3 driver gets compiled into the kernel. This is where the decisions about features, hardware support, and default settings are made. I'll be looking for things like:

*   **Dependencies:** What other kernel components or options are required for the hinic3 driver to be built? Are there any specific hardware prerequisites reflected in these dependencies?
*   **Feature Flags:** What fine-grained control do we have over different aspects of the driver's functionality? Are there options to enable or disable specific offload features, hardware acceleration, or debugging aids?
*   **Hardware Variants:** Are there different configurations for different versions or revisions of the hinic3 hardware? Does the Kconfig handle those variants in a clean and maintainable way?
*   **Defaults:** What are the default values for the configurable options? Are they sensible defaults that minimize user configuration in common scenarios?
*   **Help Text:** How well-documented are the options? The help text should provide clear explanations of what each option does and when it should be used.

Essentially, I'm expecting this file to give me the roadmap for configuring this driver, allowing me to understand (and potentially modify) the build process and tailor the driver's capabilities for specific deployments. This Kconfig file is the starting point for any in-depth configuration or troubleshooting of the hinic3 driver.



6/2 2026/10/22 23:07 tool read-file
0m Args:
{
  "File": "drivers/net/ethernet/huawei/hinic3/Kconfig",
  "FirstLine": 1,
  "LineCount": 35
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0-only\n   2:\t#\n   3:\t# Huawei driver configuration\n   4:\t#\n   5:\t\n   6:\tconfig HINIC3\n   7:\t\ttristate \"Huawei 3rd generation network adapters (HINIC3) support\"\n   8:\t\t# Fields of HW and management structures are little endian and are\n   9:\t\t# currently not converted\n  10:\t\tdepends on !CPU_BIG_ENDIAN\n  11:\t\tdepends on X86 || ARM64 || COMPILE_TEST\n  12:\t\tdepends on PCI_MSI \u0026\u0026 64BIT\n  13:\t\tselect AUXILIARY_BUS\n  14:\t\tselect DIMLIB\n  15:\t\tselect PAGE_POOL\n  16:\t\thelp\n  17:\t\t  This driver supports HiNIC 3rd gen Network Adapter (HINIC3).\n  18:\t\t  The driver is supported on X86_64 and ARM64 little endian.\n  19:\t\n  20:\t\t  To compile this driver as a module, choose M here.\n  21:\t\t  The module will be called hinic3.\n"
}

7/2 2026/10/22 23:07 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 31893
							output: 48
							thoughts: 33
						

Thoughts:
Here's my thought process, as if I were considering this issue:

**Investigating hinic3 Hardware Binding**

Okay, so I need to figure out which hardware this `hinic3` driver is actually attached to. Where do I start? The most logical approach is to go straight to the source, the core of the driver. I need to find where the PCI driver is registered, the part that actually identifies and claims the relevant hardware. `hinic3_main.c` seems like the obvious place to begin this investigation. It's likely that the initialization and PCI device probe routines would be defined there, which is what I'm looking for. Let's dig in and see what `hinic3_main.c` tells us about the binding.



8/2 2026/10/22 23:07 tool grepper
0m Args:
{
  "Expression": "pci_register_driver|hinic3_pci",
  "PathPrefixes": [
    "drivers/net/ethernet/huawei/hinic3/"
  ]
}

Results:
{
  "Output": "drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c=532=int hinic3_init_hwdev(struct pci_dev *pdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c-533-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c:534:\tstruct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c-535-\tstruct hinic3_hwdev *hwdev;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h=33=enum hinic3_fault_source_type {\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h-40-/* driver-specific data of pci_dev */\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h:41:struct hinic3_pcidev {\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h-42-\tstruct pci_dev       *pdev;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h=59=struct hinic3_hwdev {\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h:60:\tstruct hinic3_pcidev        *adapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h-61-\tstruct pci_dev              *pdev;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwif.c=447=int hinic3_init_hwif(struct hinic3_hwdev *hwdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwif.c-448-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwif.c:449:\tstruct hinic3_pcidev *pci_adapter = hwdev-\u003eadapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_hwif.c-450-\tstruct hinic3_hwif *hwif;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-12-#include \"hinic3_mgmt.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:13:#include \"hinic3_pci_id_tbl.h\"\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-14-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=94=static void hinic3_del_one_adev(struct hinic3_hwdev *hwdev,\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-96-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:97:\tstruct hinic3_pcidev *pci_adapter = hwdev-\u003eadapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-98-\tstruct hinic3_adev *hadev;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=115=static int hinic3_attach_aux_devices(struct hinic3_hwdev *hwdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-116-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:117:\tstruct hinic3_pcidev *pci_adapter = hwdev-\u003eadapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-118-\tenum hinic3_service_type svc_type;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=148=static void hinic3_detach_aux_devices(struct hinic3_hwdev *hwdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-149-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:150:\tstruct hinic3_pcidev *pci_adapter = hwdev-\u003eadapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-151-\tint i;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=188=static int hinic3_mapping_bar(struct pci_dev *pdev,\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:189:\t\t\t      struct hinic3_pcidev *pci_adapter)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-190-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-238-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:239:static void hinic3_unmapping_bar(struct hinic3_pcidev *pci_adapter)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-240-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-247-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:248:static int hinic3_pci_init(struct pci_dev *pdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-249-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:250:\tstruct hinic3_pcidev *pci_adapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-251-\tint err;\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-296-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:297:static void hinic3_pci_uninit(struct pci_dev *pdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-298-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:299:\tstruct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-300-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=309=static int hinic3_func_init(struct pci_dev *pdev,\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:310:\t\t\t    struct hinic3_pcidev *pci_adapter)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-311-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=335=static void hinic3_func_uninit(struct pci_dev *pdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-336-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:337:\tstruct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-338-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-345-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:346:static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-347-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-387-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:388:static void hinic3_remove_func(struct hinic3_pcidev *pci_adapter)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-389-{\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=396=static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-397-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:398:\tstruct hinic3_pcidev *pci_adapter;\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-399-\tint err;\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-400-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:401:\terr = hinic3_pci_init(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-402-\tif (err)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-412-err_uninit_pci:\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:413:\thinic3_pci_uninit(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-414-err_out:\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=420=static void hinic3_remove(struct pci_dev *pdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-421-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:422:\tstruct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-423-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-424-\thinic3_remove_func(pci_adapter);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:425:\thinic3_pci_uninit(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-426-}\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-427-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:428:static const struct pci_device_id hinic3_pci_table[] = {\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-429-\t{ PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_PF) },\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-433-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:434:MODULE_DEVICE_TABLE(pci, hinic3_pci_table);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-435-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=436=static void hinic3_shutdown(struct pci_dev *pdev)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-437-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:438:\tstruct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-439-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=446=static struct pci_driver hinic3_driver = {\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-447-\t.name            = HINIC3_NIC_DRV_NAME,\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:448:\t.id_table        = hinic3_pci_table,\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-449-\t.probe           = hinic3_probe,\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=455=int hinic3_lld_init(void)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-456-{\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:457:\treturn pci_register_driver(\u0026hinic3_driver);\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-458-}\n"
}

9/2 2026/10/22 23:07 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 35708
							output: 45
							thoughts: 71
						

Thoughts:
Here's my take on those thoughts:

**Analyzing the `hinic3_driver`**

Okay, so I'm looking at this `hinic3_driver` and it's immediately apparent that we're dealing with a PCI driver. The presence of `hinic3_pci_table` and the `PCI_VDEVICE` macro, specifically the reference to `HUAWEI` and `PCI_DEV_ID_HINIC3_PF`, *strongly* suggests a virtual function (VF) setup as well, which is common with these sorts of NIC drivers. Time to confirm my suspicions and verify the device IDs, so I'll need to jump over to `hinic3_pci_id_tbl.h` and take a look. I need to make sure I understand the base PCI ID, vendor ID, and device ID, to verify what it is.



10/2 2026/10/22 23:07 tool grepper
0m Args:
{
  "Expression": "PCI_DEV_ID_HINIC3",
  "PathPrefixes": [
    "drivers/net/ethernet/huawei/hinic3/"
  ]
}

Results:
{
  "Output": "drivers/net/ethernet/huawei/hinic3/hinic3_lld.c-21-\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:22:#define HINIC3_IS_VF_DEV(pdev)     ((pdev)-\u003edevice == PCI_DEV_ID_HINIC3_VF)\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-23-\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c=428=static const struct pci_device_id hinic3_pci_table[] = {\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:429:\t{ PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_PF) },\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c:430:\t{ PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_VF) },\ndrivers/net/ethernet/huawei/hinic3/hinic3_lld.c-431-\t{ }\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h-6-\ndrivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h:7:#define PCI_DEV_ID_HINIC3_PF    0x0222\ndrivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h:8:#define PCI_DEV_ID_HINIC3_VF    0x375F\ndrivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h-9-\n"
}

11/2 2026/10/22 23:07 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 36481
							output: 44
							thoughts: 397
						

Thoughts:
**My Assessment of the `hinic3` Fuzzing Feasibility**

Okay, let's go through Section 2 of the instructions, focusing on when we should return `WorthFuzzing=false`. The crucial part here is the "NEGATIVE CRITERIA," specifically, the section on "Structurally unreachable hardware." I need to determine if `hinic3` falls into this category.

First, let me clarify what `hinic3` is. It's explicitly stated as "Huawei 3rd generation network adapters (HINIC3) support". This strongly suggests it's a SmartNIC or PCIe network interface card from Huawei – very similar in nature to things like `mlxsw`, `pds_core`, and the others listed. My initial hunch is that it's going to be a hardware-dependent piece.

The question then becomes, does standard QEMU or Google Compute Engine provide any sort of emulation for this? My understanding, based on the description, is a resounding *no*. It's a proprietary ASIC/PCIe network adapter designed for Huawei servers and data centers, which is a strong indicator of hardware dependencies.

However, I need to be completely sure. I need to investigate if there's any chance that it can be instantiated virtually without the physical hardware, maybe through a virtual bus or a mock device. Let's delve into the code.

I'll start by checking `hinic3_lld.c` to see how the device is probed. Okay, `hinic3_probe` is triggered when a PCI device with the Huawei vendor ID and device IDs `0x0222` or `0x375F` is detected. Then there's an `hinic3_probe_func` that attaches auxiliary devices. Now, I need to examine `hinic3_main.c` to understand how the netdev is actually created. This will determine if it has any virtual netdev or mock driver. I need to see if it strictly requires the physical PCI device, or if there is some way to emulate.



12/2 2026/10/22 23:08 tool grepper
0m Args:
{
  "Expression": "alloc_etherdev|register_netdev",
  "PathPrefixes": [
    "drivers/net/ethernet/huawei/hinic3/"
  ]
}

Results:
{
  "Output": "drivers/net/ethernet/huawei/hinic3/hinic3_main.c=413=static int hinic3_nic_probe(struct auxiliary_device *adev,\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c-437-\tmax_qps = hinic3_func_max_qnum(hwdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c:438:\tnetdev = alloc_etherdev_mq(sizeof(*nic_dev), max_qps);\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c-439-\tif (!netdev) {\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c-468-\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c:469:\terr = register_netdev(netdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c-470-\tif (err)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c=494=static void hinic3_nic_remove(struct auxiliary_device *adev)\n--\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c-502-\tnetdev = nic_dev-\u003enetdev;\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c:503:\tunregister_netdev(netdev);\ndrivers/net/ethernet/huawei/hinic3/hinic3_main.c-504-\n"
}

13/2 2026/10/22 23:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 37795
							output: 146
							thoughts: 798
						

Thoughts:
**Analysis of the `hinic3` Driver Patch**

Okay, here's what I've got. The `hinic3_nic_probe` function, crucial to this patch's functionality, is only called on the auxiliary device created by `hinic3_attach_aux_devices`. That auxiliary device is, in turn, only created within `hinic3_probe_func`. And, here's the kicker, `hinic3_probe_func` only gets executed when the physical PCI device, specifically the Huawei ASIC/PCIe card, probes. The PCI driver itself only binds to `hinic3_pci_table` using the device IDs `PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_PF)` and `PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_VF)`. These are *Huawei* device IDs, which definitively tells me we're dealing with their proprietary hardware. Standard environments like QEMU or GCE, which syzkaller typically uses, don't emulate this kind of specialized Huawei HiNIC3 PCIe hardware.

Now, let's verify with the git diff. I reviewed the changes, and they're all isolated within `drivers/net/ethernet/huawei/hinic3/`. No other subsystems are touched, which is what I suspected. The modified files include: `hinic3_ethtool.c`, `hinic3_hw_intf.h`, `hinic3_mgmt_interface.h`, `hinic3_netdev_ops.c`, `hinic3_nic_cfg.c`, `hinic3_nic_cfg.h`, `hinic3_rx.c`, `hinic3_rx.h`, `hinic3_tx.c`, and `hinic3_tx.h`.

Based on the instructions and the "Structurally unreachable hardware" category, the answer is clear. `hinic3` is explicitly a vendor-specific SmartNIC/Ethernet PCIe adapter driver, requiring physical ASIC/PCIe hardware – Huawei's hardware, with device IDs 0x0222 or 0x375F. This definitely falls under the "structurally unreachable hardware" definition, because it requires components that aren't emulated in standard virtualized environments.

Therefore, `WorthFuzzing` has to be `false` because this patch series touches hardware we simply can't access in typical setups.

My `set-results` call will need the following:
*   `WorthFuzzing`: `false`
*   `Reasoning`: Concise: "Changes are confined to the Huawei HiNIC3 network driver (`drivers/net/ethernet/huawei/hinic3/`), which requires proprietary Huawei PCIe hardware not emulated in standard QEMU/GCE environments, making it structurally unreachable."
*   `FocusSymbols`: `[]` (empty array)
*   `EnableConfigs`: `[]` (empty array)

Alright, time to execute that `set-results` call.



14/2 2026/10/22 23:08 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The changes in this patch series are entirely confined to the Huawei HiNIC3 driver (drivers/net/ethernet/huawei/hinic3/), which is a vendor-specific Ethernet PCIe driver for Huawei SmartNIC hardware. This driver requires proprietary physical PCIe ASIC hardware (Huawei PCI vendor ID 0x19e5, device IDs 0x0222 and 0x375f) that is not emulated in standard virtualized environments (QEMU or GCE). Consequently, the modified code is structurally unreachable for fuzzing.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The changes in this patch series are entirely confined to the Huawei HiNIC3 driver (drivers/net/ethernet/huawei/hinic3/), which is a vendor-specific Ethernet PCIe driver for Huawei SmartNIC hardware. This driver requires proprietary physical PCIe ASIC hardware (Huawei PCI vendor ID 0x19e5, device IDs 0x0222 and 0x375f) that is not emulated in standard virtualized environments (QEMU or GCE). Consequently, the modified code is structurally unreachable for fuzzing.",
  "WorthFuzzing": false
}

15/1 2026/10/22 23:08 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)