From nobody Tue Dec 2 02:32:01 2025 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 54BA63590A3; Wed, 19 Nov 2025 12:44:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763556253; cv=none; b=ukQ0l4ZjIL5/W1gFu3/RvIB521h8yE1304o0lWVc5oN0xLZX91Yp/QjyoSUmywBi6kpwdYwWucEqcFIGCIBb0R/LyiCW1eJqlyCsVWACT+yHyPcgLzSnOlFP8DvQ+8V/+ntXltbyuICZCLINasS4k4Vw6EL9H5eYw8m3ux0OkfI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763556253; c=relaxed/simple; bh=V5zPEgQ7V0aKomvP5bLgA4HXTUrs+9cQus7O5AqNaRg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HoUaiFEoytyjoO45tGrJz0LpM9AJdQODS05P3ddIu5th1KHLeD6wHRPyrnv/NQEVhJi1yBI1jVdtlZFvtU9RU6oh8glc8h3K9ez9DUOUQe9qfxB5T6oCptFZP/8ySDe2c4Ic+RN3OUAEMhGEC8T6gtoQUX5btJyqRzfymLsyK/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=QD489fAl; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="QD489fAl" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=Vt4RfNnxosKtTjHH0aWHYwqePHpE9SDJvLjva/kFwHA=; b=QD489fAlAMFCSEH7uxnzZEsxjq9Sq3lCmtIIExsch+wT+Hh8zeAfbAsypfqsPt4PELau45zlA v1vgZDK+SSU9MXxj+wmB9oe/Lft/vWjAnLKM/vdxVhx3FR8v9h7rM8g2JANQsv7bBBWWurI3uEs dKfNdCdfpA0ruT6aTXL817c= Received: from mail.maildlp.com (unknown [172.19.163.252]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4dBLhs44VGzpSwp; Wed, 19 Nov 2025 20:42:05 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id D96E2180B56; Wed, 19 Nov 2025 20:44:00 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.188.120) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Wed, 19 Nov 2025 20:43:59 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , Markus Elfring , Pavan Chebbi , ALOK TIWARI CC: , , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi Subject: [PATCH net-next v07 3/9] hinic3: Add .ndo_tx_timeout and .ndo_get_stats64 Date: Wed, 19 Nov 2025 20:43:36 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Implement following callback function: .ndo_tx_timeout .ndo_get_stats64 Use a work queue to trace tx_timeout callback and dump necessary debug information. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../net/ethernet/huawei/hinic3/hinic3_hwdev.h | 9 +++ .../net/ethernet/huawei/hinic3/hinic3_main.c | 39 +++++++++- .../huawei/hinic3/hinic3_netdev_ops.c | 77 +++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 8 ++ .../net/ethernet/huawei/hinic3/hinic3_rx.h | 15 ++++ .../net/ethernet/huawei/hinic3/hinic3_tx.h | 16 ++++ 6 files changed, 162 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.h index 3c15f22973fe..58bc561f95b3 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h @@ -17,6 +17,15 @@ enum hinic3_event_service_type { HINIC3_EVENT_SRV_NIC =3D 1 }; =20 +enum hinic3_fault_err_level { + HINIC3_FAULT_LEVEL_SERIOUS_FLR =3D 3, +}; + +enum hinic3_fault_source_type { + HINIC3_FAULT_SRC_HW_PHY_FAULT =3D 9, + HINIC3_FAULT_SRC_TX_TIMEOUT =3D 22, +}; + #define HINIC3_SRV_EVENT_TYPE(svc, type) (((svc) << 16) | (type)) =20 /* driver-specific data of pci_dev */ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_main.c index ce10ae7c0d9e..4503c9303ee4 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c @@ -108,6 +108,22 @@ static void hinic3_free_txrxqs(struct net_device *netd= ev) hinic3_free_txqs(netdev); } =20 +static void hinic3_periodic_work_handler(struct work_struct *work) +{ + struct delayed_work *delay =3D to_delayed_work(work); + struct hinic3_nic_dev *nic_dev; + + nic_dev =3D container_of(delay, struct hinic3_nic_dev, periodic_work); + if (test_and_clear_bit(HINIC3_EVENT_WORK_TX_TIMEOUT, + &nic_dev->event_flag)) + dev_info(nic_dev->hwdev->dev, + "Fault event report, src: %u, level: %u\n", + HINIC3_FAULT_SRC_TX_TIMEOUT, + HINIC3_FAULT_LEVEL_SERIOUS_FLR); + + queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); +} + static int hinic3_init_nic_dev(struct net_device *netdev, struct hinic3_hwdev *hwdev) { @@ -123,6 +139,15 @@ static int hinic3_init_nic_dev(struct net_device *netd= ev, nic_dev->lro_replenish_thld =3D HINIC3_LRO_REPLENISH_THLD; nic_dev->nic_svc_cap =3D hwdev->cfg_mgmt->cap.nic_svc_cap; =20 + nic_dev->workq =3D create_singlethread_workqueue(HINIC3_NIC_DEV_WQ_NAME); + if (!nic_dev->workq) { + dev_err(hwdev->dev, "Failed to initialize nic workqueue\n"); + return -ENOMEM; + } + + INIT_DELAYED_WORK(&nic_dev->periodic_work, + hinic3_periodic_work_handler); + return 0; } =20 @@ -276,6 +301,11 @@ static void hinic3_nic_event(struct auxiliary_device *= adev, } } =20 +static void hinic3_free_nic_dev(struct hinic3_nic_dev *nic_dev) +{ + destroy_workqueue(nic_dev->workq); +} + static int hinic3_nic_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { @@ -316,7 +346,7 @@ static int hinic3_nic_probe(struct auxiliary_device *ad= ev, =20 err =3D hinic3_init_nic_io(nic_dev); if (err) - goto err_free_netdev; + goto err_free_nic_dev; =20 err =3D hinic3_sw_init(netdev); if (err) @@ -329,6 +359,7 @@ static int hinic3_nic_probe(struct auxiliary_device *ad= ev, if (err) goto err_uninit_sw; =20 + queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); netif_carrier_off(netdev); =20 err =3D register_netdev(netdev); @@ -346,7 +377,8 @@ static int hinic3_nic_probe(struct auxiliary_device *ad= ev, =20 err_free_nic_io: hinic3_free_nic_io(nic_dev); - +err_free_nic_dev: + hinic3_free_nic_dev(nic_dev); err_free_netdev: free_netdev(netdev); =20 @@ -368,6 +400,9 @@ static void hinic3_nic_remove(struct auxiliary_device *= adev) netdev =3D nic_dev->netdev; unregister_netdev(netdev); =20 + disable_delayed_work_sync(&nic_dev->periodic_work); + hinic3_free_nic_dev(nic_dev); + hinic3_update_nic_feature(nic_dev, 0); hinic3_set_nic_feature_to_hw(nic_dev); hinic3_sw_uninit(netdev); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index 3d371291ad04..16a17deb15d8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -517,11 +517,88 @@ static int hinic3_set_mac_addr(struct net_device *net= dev, void *addr) return 0; } =20 +static void hinic3_tx_timeout(struct net_device *netdev, unsigned int txqu= eue) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_io_queue *sq; + u16 sw_pi, hw_ci; + + sq =3D nic_dev->txqs[txqueue].sq; + sw_pi =3D hinic3_get_sq_local_pi(sq); + hw_ci =3D hinic3_get_sq_hw_ci(sq); + netdev_dbg(netdev, + "txq%u: sw_pi: %u, hw_ci: %u, sw_ci: %u, napi->state: 0x%lx.\n", + txqueue, sw_pi, hw_ci, hinic3_get_sq_local_ci(sq), + nic_dev->q_params.irq_cfg[txqueue].napi.state); + + if (sw_pi !=3D hw_ci) + set_bit(HINIC3_EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag); +} + +static void hinic3_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u64 bytes, packets, dropped, errors; + struct hinic3_txq_stats *txq_stats; + struct hinic3_rxq_stats *rxq_stats; + struct hinic3_txq *txq; + struct hinic3_rxq *rxq; + unsigned int start; + int i; + + bytes =3D 0; + packets =3D 0; + dropped =3D 0; + for (i =3D 0; i < nic_dev->max_qps; i++) { + if (!nic_dev->txqs) + break; + + txq =3D &nic_dev->txqs[i]; + txq_stats =3D &txq->txq_stats; + do { + start =3D u64_stats_fetch_begin(&txq_stats->syncp); + bytes +=3D txq_stats->bytes; + packets +=3D txq_stats->packets; + dropped +=3D txq_stats->dropped; + } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); + } + stats->tx_packets =3D packets; + stats->tx_bytes =3D bytes; + stats->tx_dropped =3D dropped; + + bytes =3D 0; + packets =3D 0; + errors =3D 0; + dropped =3D 0; + for (i =3D 0; i < nic_dev->max_qps; i++) { + if (!nic_dev->rxqs) + break; + + rxq =3D &nic_dev->rxqs[i]; + rxq_stats =3D &rxq->rxq_stats; + do { + start =3D u64_stats_fetch_begin(&rxq_stats->syncp); + bytes +=3D rxq_stats->bytes; + packets +=3D rxq_stats->packets; + errors +=3D rxq_stats->csum_errors + + rxq_stats->other_errors; + dropped +=3D rxq_stats->dropped; + } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); + } + stats->rx_packets =3D packets; + stats->rx_bytes =3D bytes; + stats->rx_errors =3D errors; + stats->rx_dropped =3D dropped; +} + static const struct net_device_ops hinic3_netdev_ops =3D { .ndo_open =3D hinic3_open, .ndo_stop =3D hinic3_close, .ndo_change_mtu =3D hinic3_change_mtu, .ndo_set_mac_address =3D hinic3_set_mac_addr, + .ndo_tx_timeout =3D hinic3_tx_timeout, + .ndo_get_stats64 =3D hinic3_get_stats64, .ndo_start_xmit =3D hinic3_xmit_frame, }; =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_dev.h index 52bcf6fb14f2..b8c9c325a45a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h @@ -13,6 +13,10 @@ enum hinic3_flags { HINIC3_RSS_ENABLE, }; =20 +enum hinic3_event_work_flags { + HINIC3_EVENT_WORK_TX_TIMEOUT, +}; + enum hinic3_rss_hash_type { HINIC3_RSS_HASH_ENGINE_TYPE_XOR =3D 0, HINIC3_RSS_HASH_ENGINE_TYPE_TOEP =3D 1, @@ -83,9 +87,13 @@ struct hinic3_nic_dev { =20 struct hinic3_intr_coal_info *intr_coalesce; =20 + struct workqueue_struct *workq; + struct delayed_work periodic_work; /* lock for enable/disable port */ struct mutex port_state_mutex; =20 + /* flag bits defined by hinic3_event_work_flags */ + unsigned long event_flag; bool link_status_up; }; =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.h index 44ae841a3648..68fc237d642b 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h @@ -25,6 +25,20 @@ #define RQ_CQE_STATUS_GET(val, member) \ FIELD_GET(RQ_CQE_STATUS_##member##_MASK, val) =20 +struct hinic3_rxq_stats { + u64 packets; + u64 bytes; + u64 errors; + u64 csum_errors; + u64 other_errors; + u64 dropped; + u64 rx_buf_empty; + u64 alloc_skb_err; + u64 alloc_rx_buf_err; + u64 restore_drop_sge; + struct u64_stats_sync syncp; +}; + /* RX Completion information that is provided by HW for a specific RX WQE = */ struct hinic3_rq_cqe { __le32 status; @@ -59,6 +73,7 @@ struct hinic3_rxq { u16 buf_len; u32 buf_len_shift; =20 + struct hinic3_rxq_stats rxq_stats; u32 cons_idx; u32 delta; =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.h index 7e1b872ba752..00194f2a1bcc 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h @@ -100,6 +100,20 @@ struct hinic3_sq_wqe_combo { u32 task_type; }; =20 +struct hinic3_txq_stats { + u64 packets; + u64 bytes; + 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; +}; + struct hinic3_dma_info { dma_addr_t dma; u32 len; @@ -123,6 +137,8 @@ struct hinic3_txq { =20 struct hinic3_tx_info *tx_info; struct hinic3_io_queue *sq; + + struct hinic3_txq_stats txq_stats; } ____cacheline_aligned; =20 struct hinic3_dyna_txq_res { --=20 2.43.0