Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'hinic-dev_get_stats-fixes'

Qiao Ma says:

====================
net: hinic: fix bugs about dev_get_stats

These patches fixes 2 bugs of hinic driver:
- fix bug that ethtool get wrong stats because of hinic_{txq|rxq}_clean_stats() is called
- avoid kernel hung in hinic_get_stats64()

See every patch for more information.

Changes in v4:
- removed meaningless u64_stats_sync protection in hinic_{txq|rxq}_get_stats
- merged the third patch in v2 into first one

Changes in v3:
- fixes a compile warning reported by kernel test robot <lkp@intel.com>

Changes in v2:
- fixes another 2 bugs. (v1 is a single patch, see: https://lore.kernel.org/all/07736c2b7019b6883076a06129e06e8f7c5f7154.1656487154.git.mqaio@linux.alibaba.com/).
- to fix extra bugs, hinic_dev.tx_stats/rx_stats is removed, so there is no need to use spinlock or semaphore now.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+16 -52
-3
drivers/net/ethernet/huawei/hinic/hinic_dev.h
··· 95 95 u16 sq_depth; 96 96 u16 rq_depth; 97 97 98 - struct hinic_txq_stats tx_stats; 99 - struct hinic_rxq_stats rx_stats; 100 - 101 98 u8 rss_tmpl_idx; 102 99 u8 rss_hash_engine; 103 100 u16 num_rss;
+16 -45
drivers/net/ethernet/huawei/hinic/hinic_main.c
··· 80 80 netdev_features_t pre_features, 81 81 netdev_features_t features, bool force_change); 82 82 83 - static void update_rx_stats(struct hinic_dev *nic_dev, struct hinic_rxq *rxq) 83 + static void gather_rx_stats(struct hinic_rxq_stats *nic_rx_stats, struct hinic_rxq *rxq) 84 84 { 85 - struct hinic_rxq_stats *nic_rx_stats = &nic_dev->rx_stats; 86 85 struct hinic_rxq_stats rx_stats; 87 - 88 - u64_stats_init(&rx_stats.syncp); 89 86 90 87 hinic_rxq_get_stats(rxq, &rx_stats); 91 88 92 - u64_stats_update_begin(&nic_rx_stats->syncp); 93 89 nic_rx_stats->bytes += rx_stats.bytes; 94 90 nic_rx_stats->pkts += rx_stats.pkts; 95 91 nic_rx_stats->errors += rx_stats.errors; 96 92 nic_rx_stats->csum_errors += rx_stats.csum_errors; 97 93 nic_rx_stats->other_errors += rx_stats.other_errors; 98 - u64_stats_update_end(&nic_rx_stats->syncp); 99 - 100 - hinic_rxq_clean_stats(rxq); 101 94 } 102 95 103 - static void update_tx_stats(struct hinic_dev *nic_dev, struct hinic_txq *txq) 96 + static void gather_tx_stats(struct hinic_txq_stats *nic_tx_stats, struct hinic_txq *txq) 104 97 { 105 - struct hinic_txq_stats *nic_tx_stats = &nic_dev->tx_stats; 106 98 struct hinic_txq_stats tx_stats; 107 - 108 - u64_stats_init(&tx_stats.syncp); 109 99 110 100 hinic_txq_get_stats(txq, &tx_stats); 111 101 112 - u64_stats_update_begin(&nic_tx_stats->syncp); 113 102 nic_tx_stats->bytes += tx_stats.bytes; 114 103 nic_tx_stats->pkts += tx_stats.pkts; 115 104 nic_tx_stats->tx_busy += tx_stats.tx_busy; 116 105 nic_tx_stats->tx_wake += tx_stats.tx_wake; 117 106 nic_tx_stats->tx_dropped += tx_stats.tx_dropped; 118 107 nic_tx_stats->big_frags_pkts += tx_stats.big_frags_pkts; 119 - u64_stats_update_end(&nic_tx_stats->syncp); 120 - 121 - hinic_txq_clean_stats(txq); 122 108 } 123 109 124 - static void update_nic_stats(struct hinic_dev *nic_dev) 110 + static void gather_nic_stats(struct hinic_dev *nic_dev, 111 + struct hinic_rxq_stats *nic_rx_stats, 112 + struct hinic_txq_stats *nic_tx_stats) 125 113 { 126 114 int i, num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); 127 115 128 116 for (i = 0; i < num_qps; i++) 129 - update_rx_stats(nic_dev, &nic_dev->rxqs[i]); 117 + gather_rx_stats(nic_rx_stats, &nic_dev->rxqs[i]); 130 118 131 119 for (i = 0; i < num_qps; i++) 132 - update_tx_stats(nic_dev, &nic_dev->txqs[i]); 120 + gather_tx_stats(nic_tx_stats, &nic_dev->txqs[i]); 133 121 } 134 122 135 123 /** ··· 546 558 netif_carrier_off(netdev); 547 559 netif_tx_disable(netdev); 548 560 549 - update_nic_stats(nic_dev); 550 - 551 561 up(&nic_dev->mgmt_lock); 552 562 553 563 if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) ··· 839 853 struct rtnl_link_stats64 *stats) 840 854 { 841 855 struct hinic_dev *nic_dev = netdev_priv(netdev); 842 - struct hinic_rxq_stats *nic_rx_stats; 843 - struct hinic_txq_stats *nic_tx_stats; 844 - 845 - nic_rx_stats = &nic_dev->rx_stats; 846 - nic_tx_stats = &nic_dev->tx_stats; 847 - 848 - down(&nic_dev->mgmt_lock); 856 + struct hinic_rxq_stats nic_rx_stats = {}; 857 + struct hinic_txq_stats nic_tx_stats = {}; 849 858 850 859 if (nic_dev->flags & HINIC_INTF_UP) 851 - update_nic_stats(nic_dev); 860 + gather_nic_stats(nic_dev, &nic_rx_stats, &nic_tx_stats); 852 861 853 - up(&nic_dev->mgmt_lock); 862 + stats->rx_bytes = nic_rx_stats.bytes; 863 + stats->rx_packets = nic_rx_stats.pkts; 864 + stats->rx_errors = nic_rx_stats.errors; 854 865 855 - stats->rx_bytes = nic_rx_stats->bytes; 856 - stats->rx_packets = nic_rx_stats->pkts; 857 - stats->rx_errors = nic_rx_stats->errors; 858 - 859 - stats->tx_bytes = nic_tx_stats->bytes; 860 - stats->tx_packets = nic_tx_stats->pkts; 861 - stats->tx_errors = nic_tx_stats->tx_dropped; 866 + stats->tx_bytes = nic_tx_stats.bytes; 867 + stats->tx_packets = nic_tx_stats.pkts; 868 + stats->tx_errors = nic_tx_stats.tx_dropped; 862 869 } 863 870 864 871 static int hinic_set_features(struct net_device *netdev, ··· 1150 1171 static int nic_dev_init(struct pci_dev *pdev) 1151 1172 { 1152 1173 struct hinic_rx_mode_work *rx_mode_work; 1153 - struct hinic_txq_stats *tx_stats; 1154 - struct hinic_rxq_stats *rx_stats; 1155 1174 struct hinic_dev *nic_dev; 1156 1175 struct net_device *netdev; 1157 1176 struct hinic_hwdev *hwdev; ··· 1210 1233 hinic_set_ethtool_ops(netdev); 1211 1234 1212 1235 sema_init(&nic_dev->mgmt_lock, 1); 1213 - 1214 - tx_stats = &nic_dev->tx_stats; 1215 - rx_stats = &nic_dev->rx_stats; 1216 - 1217 - u64_stats_init(&tx_stats->syncp); 1218 - u64_stats_init(&rx_stats->syncp); 1219 1236 1220 1237 nic_dev->vlan_bitmap = devm_bitmap_zalloc(&pdev->dev, VLAN_N_VID, 1221 1238 GFP_KERNEL);
-2
drivers/net/ethernet/huawei/hinic/hinic_rx.c
··· 73 73 struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats; 74 74 unsigned int start; 75 75 76 - u64_stats_update_begin(&stats->syncp); 77 76 do { 78 77 start = u64_stats_fetch_begin(&rxq_stats->syncp); 79 78 stats->pkts = rxq_stats->pkts; ··· 82 83 stats->csum_errors = rxq_stats->csum_errors; 83 84 stats->other_errors = rxq_stats->other_errors; 84 85 } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); 85 - u64_stats_update_end(&stats->syncp); 86 86 } 87 87 88 88 /**
-2
drivers/net/ethernet/huawei/hinic/hinic_tx.c
··· 98 98 struct hinic_txq_stats *txq_stats = &txq->txq_stats; 99 99 unsigned int start; 100 100 101 - u64_stats_update_begin(&stats->syncp); 102 101 do { 103 102 start = u64_stats_fetch_begin(&txq_stats->syncp); 104 103 stats->pkts = txq_stats->pkts; ··· 107 108 stats->tx_dropped = txq_stats->tx_dropped; 108 109 stats->big_frags_pkts = txq_stats->big_frags_pkts; 109 110 } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); 110 - u64_stats_update_end(&stats->syncp); 111 111 } 112 112 113 113 /**